1 /*
2 Source:
3 http://www1.cse.wustl.edu/~schmidt/ACE-copying.html
4
5 License:
6 Copyright and Licensing Information for ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM),
7 and CoSMIC(TM)
8
9 ACE(TM), TAO(TM), CIAO(TM), DAnCE>(TM), and CoSMIC(TM) (henceforth referred to
10 as "DOC software") are copyrighted by Douglas C. Schmidt and his research
11 group at Washington University, University of California, Irvine, and
12 Vanderbilt University, Copyright (c) 1993-2009, all rights reserved. Since DOC
13 software is open-source, freely available software, you are free to use,
14 modify, copy, and distribute--perpetually and irrevocably--the DOC software
15 source code and object code produced from the source, as well as copy and
16 distribute modified versions of this software. You must, however, include this
17 copyright statement along with any code built using DOC software that you
18 release. No copyright statement needs to be provided if you just ship binary
19 executables of your software products.
20 You can use DOC software in commercial and/or binary software releases and are
21 under no obligation to redistribute any of your source code that is built
22 using DOC software. Note, however, that you may not misappropriate the DOC
23 software code, such as copyrighting it yourself or claiming authorship of the
24 DOC software code, in a way that will prevent DOC software from being
25 distributed freely using an open-source development model. You needn't inform
26 anyone that you're using DOC software in your software, though we encourage
27 you to let us know so we can promote your project in the DOC software success
28 stories.
29
30 The ACE, TAO, CIAO, DAnCE, and CoSMIC web sites are maintained by the DOC
31 Group at the Institute for Software Integrated Systems (ISIS) and the Center
32 for Distributed Object Computing of Washington University, St. Louis for the
33 development of open-source software as part of the open-source software
34 community. Submissions are provided by the submitter ``as is'' with no
35 warranties whatsoever, including any warranty of merchantability,
36 noninfringement of third party intellectual property, or fitness for any
37 particular purpose. In no event shall the submitter be liable for any direct,
38 indirect, special, exemplary, punitive, or consequential damages, including
39 without limitation, lost profits, even if advised of the possibility of such
40 damages. Likewise, DOC software is provided as is with no warranties of any
41 kind, including the warranties of design, merchantability, and fitness for a
42 particular purpose, noninfringement, or arising from a course of dealing,
43 usage or trade practice. Washington University, UC Irvine, Vanderbilt
44 University, their employees, and students shall have no liability with respect
45 to the infringement of copyrights, trade secrets or any patents by DOC
46 software or any part thereof. Moreover, in no event will Washington
47 University, UC Irvine, or Vanderbilt University, their employees, or students
48 be liable for any lost revenue or profits or other special, indirect and
49 consequential damages.
50
51 DOC software is provided with no support and without any obligation on the
52 part of Washington University, UC Irvine, Vanderbilt University, their
53 employees, or students to assist in its use, correction, modification, or
54 enhancement. A number of companies around the world provide commercial support
55 for DOC software, however. DOC software is Y2K-compliant, as long as the
56 underlying OS platform is Y2K-compliant. Likewise, DOC software is compliant
57 with the new US daylight savings rule passed by Congress as "The Energy Policy
58 Act of 2005," which established new daylight savings times (DST) rules for the
59 United States that expand DST as of March 2007. Since DOC software obtains
60 time/date and calendaring information from operating systems users will not be
61 affected by the new DST rules as long as they upgrade their operating systems
62 accordingly.
63
64 The names ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), CoSMIC(TM), Washington
65 University, UC Irvine, and Vanderbilt University, may not be used to endorse
66 or promote products or services derived from this source without express
67 written permission from Washington University, UC Irvine, or Vanderbilt
68 University. This license grants no permission to call products or services
69 derived from this source ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), or CoSMIC(TM),
70 nor does it grant permission for the name Washington University, UC Irvine, or
71 Vanderbilt University to appear in their names.
72 */
73
74 /*
75 * This source code contain modifications to the original source code
76 * which can be found here:
77 * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html (section 3.2).
78 * Modifications:
79 * 1) Dynamic detection of native support for condition variables.
80 * 2) Use of WebRTC defined types and classes. Renaming of some functions.
81 * 3) Introduction of a second event for wake all functionality. This prevents
82 * a thread from spinning on the same condition variable, preventing other
83 * threads from waking up.
84 */
85
86 #include "webrtc/system_wrappers/source/condition_variable_event_win.h"
87 #include "webrtc/system_wrappers/source/critical_section_win.h"
88
89 namespace webrtc {
90
ConditionVariableEventWin()91 ConditionVariableEventWin::ConditionVariableEventWin() : eventID_(WAKEALL_0) {
92 memset(&num_waiters_[0], 0, sizeof(num_waiters_));
93
94 InitializeCriticalSection(&num_waiters_crit_sect_);
95
96 events_[WAKEALL_0] = CreateEvent(NULL, // no security attributes
97 TRUE, // manual-reset, sticky event
98 FALSE, // initial state non-signaled
99 NULL); // no name for event
100
101 events_[WAKEALL_1] = CreateEvent(NULL, // no security attributes
102 TRUE, // manual-reset, sticky event
103 FALSE, // initial state non-signaled
104 NULL); // no name for event
105
106 events_[WAKE] = CreateEvent(NULL, // no security attributes
107 FALSE, // auto-reset, sticky event
108 FALSE, // initial state non-signaled
109 NULL); // no name for event
110 }
111
~ConditionVariableEventWin()112 ConditionVariableEventWin::~ConditionVariableEventWin() {
113 CloseHandle(events_[WAKE]);
114 CloseHandle(events_[WAKEALL_1]);
115 CloseHandle(events_[WAKEALL_0]);
116
117 DeleteCriticalSection(&num_waiters_crit_sect_);
118 }
119
SleepCS(CriticalSectionWrapper & crit_sect)120 void ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect) {
121 SleepCS(crit_sect, INFINITE);
122 }
123
SleepCS(CriticalSectionWrapper & crit_sect,unsigned long max_time_in_ms)124 bool ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect,
125 unsigned long max_time_in_ms) {
126 EnterCriticalSection(&num_waiters_crit_sect_);
127
128 // Get the eventID for the event that will be triggered by next
129 // WakeAll() call and start waiting for it.
130 const EventWakeUpType eventID =
131 (WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0;
132
133 ++(num_waiters_[eventID]);
134 LeaveCriticalSection(&num_waiters_crit_sect_);
135
136 CriticalSectionWindows* cs =
137 static_cast<CriticalSectionWindows*>(&crit_sect);
138 LeaveCriticalSection(&cs->crit);
139 HANDLE events[2];
140 events[0] = events_[WAKE];
141 events[1] = events_[eventID];
142 const DWORD result = WaitForMultipleObjects(2, // Wait on 2 events.
143 events,
144 FALSE, // Wait for either.
145 max_time_in_ms);
146
147 const bool ret_val = (result != WAIT_TIMEOUT);
148
149 EnterCriticalSection(&num_waiters_crit_sect_);
150 --(num_waiters_[eventID]);
151
152 // Last waiter should only be true for WakeAll(). WakeAll() correspond
153 // to position 1 in events[] -> (result == WAIT_OBJECT_0 + 1)
154 const bool last_waiter = (result == WAIT_OBJECT_0 + 1) &&
155 (num_waiters_[eventID] == 0);
156 LeaveCriticalSection(&num_waiters_crit_sect_);
157
158 if (last_waiter) {
159 // Reset/unset the WakeAll() event since all threads have been
160 // released.
161 ResetEvent(events_[eventID]);
162 }
163
164 EnterCriticalSection(&cs->crit);
165 return ret_val;
166 }
167
Wake()168 void ConditionVariableEventWin::Wake() {
169 EnterCriticalSection(&num_waiters_crit_sect_);
170 const bool have_waiters = (num_waiters_[WAKEALL_0] > 0) ||
171 (num_waiters_[WAKEALL_1] > 0);
172 LeaveCriticalSection(&num_waiters_crit_sect_);
173
174 if (have_waiters) {
175 SetEvent(events_[WAKE]);
176 }
177 }
178
WakeAll()179 void ConditionVariableEventWin::WakeAll() {
180 EnterCriticalSection(&num_waiters_crit_sect_);
181
182 // Update current WakeAll() event
183 eventID_ = (WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0;
184
185 // Trigger current event
186 const EventWakeUpType eventID = eventID_;
187 const bool have_waiters = num_waiters_[eventID] > 0;
188 LeaveCriticalSection(&num_waiters_crit_sect_);
189
190 if (have_waiters) {
191 SetEvent(events_[eventID]);
192 }
193 }
194
195 } // namespace webrtc
196