RCFProto

- Main Page
- Classes
- Files

- File List

All Classes Functions Typedefs
win_event.hpp
1
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2013, Delta V Software. All rights reserved.
6 // http://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF
12 // under GPL terms.
13 //
14 // Version: 2.0
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18
19 //
20 // detail/win_event.hpp
21 // ~~~~~~~~~~~~~~~~~~~~
22 //
23 // Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
24 //
25 // Distributed under the Boost Software License, Version 1.0. (See accompanying
26 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
27 //
28
29 #ifndef RCF_DETAIL_WIN_EVENT_HPP
30 #define RCF_DETAIL_WIN_EVENT_HPP
31
32 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
33 # pragma once
34 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
35
36 #if defined(BOOST_WINDOWS)
37
38 #include <boost/assert.hpp>
39
40 #include <RCF/thread/push_options.hpp>
41
42 #include <RCF/thread/mutex.hpp>
43
44 namespace RCF {
45 namespace detail {
46
47 class RCF_EXPORT win_event
48 : private noncopyable
49 {
50 public:
51 // Constructor.
52 win_event();
53
54 // Destructor.
55 ~win_event()
56 {
57 ::CloseHandle(event_);
58 }
59
60 // Signal the event.
61 template <typename Lock>
62 void signal_all(Lock& lock)
63 {
64 BOOST_ASSERT(lock.locked());
65 (void)lock;
66 if (mWaitCount > 0)
67 {
68 ::SetEvent(event_);
69 }
70 }
71
72 // Reset the event.
73 template <typename Lock>
74 void clear(Lock& lock)
75 {
76 BOOST_ASSERT(lock.locked());
77 (void)lock;
78 ::ResetEvent(event_);
79 }
80
81 // Wait for the event to become signalled.
82 template <typename Lock>
83 void wait(Lock& lock)
84 {
85 BOOST_ASSERT(lock.locked());
86 lock.unlock();
87
88 {
89 mutex::scoped_lock lock(mWaitCountMutex);
90 ++mWaitCount;
91 }
92
93 ::WaitForSingleObject(event_, INFINITE);
94
95 {
96 mutex::scoped_lock lock(mWaitCountMutex);
97 --mWaitCount;
98 if (mWaitCount == 0)
99 {
100 // Set signalled state back to false.
101 ::ResetEvent(event_);
102 }
103 }
104
105 lock.lock();
106
107 }
108
109 // Wait for the event to become signalled.
110 template <typename Lock>
111 bool timed_wait(Lock& lock, boost::uint32_t waitMs)
112 {
113 BOOST_ASSERT(lock.locked());
114
115 lock.unlock();
116
117 {
118 mutex::scoped_lock lock(mWaitCountMutex);
119 ++mWaitCount;
120 }
121
122 DWORD ret = ::WaitForSingleObject(event_, waitMs);
123 assert(ret != WAIT_ABANDONED && ret != WAIT_FAILED);
124
125 {
126 mutex::scoped_lock lock(mWaitCountMutex);
127 --mWaitCount;
128 if (ret != WAIT_TIMEOUT && mWaitCount == 0)
129 {
130 // Set signalled state back to false.
131 ::ResetEvent(event_);
132 }
133 }
134
135 lock.lock();
136 if (ret == WAIT_TIMEOUT)
137 {
138 return false;
139 }
140
141 return true;
142 }
143
144 // Signal the event.
145 template <typename Lock>
146 void notify_all(Lock& lock)
147 {
148 signal_all(lock);
149 }
150
151 protected:
152
153 // Newer versions of Windows have built in condition variables (InitializeConditionVariable() etc)
154 // but they are not supported in XP, Server 2003, and older. So for now we use
155 // events instead, with the mWatiCount workaround below for resetting the event.
156 HANDLE event_;
157
158 // Number of threads waiting on the event. When the threads are signalled,
159 // the counter is decremented, and the thread that decrements the counter
160 // to zero will reset the event. The event is a "manual reset" event, as
161 // an "auto reset" event only releases 1 thread at a time.
162 mutex mWaitCountMutex;
163 int mWaitCount;
164 };
165
166 } // namespace detail
167 } // namespace RCF
168
169 #include <RCF/thread/pop_options.hpp>
170
171 #endif // defined(BOOST_WINDOWS)
172
173 #endif // RCF_DETAIL_WIN_EVENT_HPP