1/* 2Source: 3http://www1.cse.wustl.edu/~schmidt/ACE-copying.html 4 5License: 6Copyright and Licensing Information for ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), 7and CoSMIC(TM) 8 9ACE(TM), TAO(TM), CIAO(TM), DAnCE>(TM), and CoSMIC(TM) (henceforth referred to 10as "DOC software") are copyrighted by Douglas C. Schmidt and his research 11group at Washington University, University of California, Irvine, and 12Vanderbilt University, Copyright (c) 1993-2009, all rights reserved. Since DOC 13software is open-source, freely available software, you are free to use, 14modify, copy, and distribute--perpetually and irrevocably--the DOC software 15source code and object code produced from the source, as well as copy and 16distribute modified versions of this software. You must, however, include this 17copyright statement along with any code built using DOC software that you 18release. No copyright statement needs to be provided if you just ship binary 19executables of your software products. 20You can use DOC software in commercial and/or binary software releases and are 21under no obligation to redistribute any of your source code that is built 22using DOC software. Note, however, that you may not misappropriate the DOC 23software code, such as copyrighting it yourself or claiming authorship of the 24DOC software code, in a way that will prevent DOC software from being 25distributed freely using an open-source development model. You needn't inform 26anyone that you're using DOC software in your software, though we encourage 27you to let us know so we can promote your project in the DOC software success 28stories. 29 30The ACE, TAO, CIAO, DAnCE, and CoSMIC web sites are maintained by the DOC 31Group at the Institute for Software Integrated Systems (ISIS) and the Center 32for Distributed Object Computing of Washington University, St. Louis for the 33development of open-source software as part of the open-source software 34community. Submissions are provided by the submitter ``as is'' with no 35warranties whatsoever, including any warranty of merchantability, 36noninfringement of third party intellectual property, or fitness for any 37particular purpose. In no event shall the submitter be liable for any direct, 38indirect, special, exemplary, punitive, or consequential damages, including 39without limitation, lost profits, even if advised of the possibility of such 40damages. Likewise, DOC software is provided as is with no warranties of any 41kind, including the warranties of design, merchantability, and fitness for a 42particular purpose, noninfringement, or arising from a course of dealing, 43usage or trade practice. Washington University, UC Irvine, Vanderbilt 44University, their employees, and students shall have no liability with respect 45to the infringement of copyrights, trade secrets or any patents by DOC 46software or any part thereof. Moreover, in no event will Washington 47University, UC Irvine, or Vanderbilt University, their employees, or students 48be liable for any lost revenue or profits or other special, indirect and 49consequential damages. 50 51DOC software is provided with no support and without any obligation on the 52part of Washington University, UC Irvine, Vanderbilt University, their 53employees, or students to assist in its use, correction, modification, or 54enhancement. A number of companies around the world provide commercial support 55for DOC software, however. DOC software is Y2K-compliant, as long as the 56underlying OS platform is Y2K-compliant. Likewise, DOC software is compliant 57with the new US daylight savings rule passed by Congress as "The Energy Policy 58Act of 2005," which established new daylight savings times (DST) rules for the 59United States that expand DST as of March 2007. Since DOC software obtains 60time/date and calendaring information from operating systems users will not be 61affected by the new DST rules as long as they upgrade their operating systems 62accordingly. 63 64The names ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), CoSMIC(TM), Washington 65University, UC Irvine, and Vanderbilt University, may not be used to endorse 66or promote products or services derived from this source without express 67written permission from Washington University, UC Irvine, or Vanderbilt 68University. This license grants no permission to call products or services 69derived from this source ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), or CoSMIC(TM), 70nor does it grant permission for the name Washington University, UC Irvine, or 71Vanderbilt 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 89namespace webrtc { 90 91ConditionVariableEventWin::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 112ConditionVariableEventWin::~ConditionVariableEventWin() { 113 CloseHandle(events_[WAKE]); 114 CloseHandle(events_[WAKEALL_1]); 115 CloseHandle(events_[WAKEALL_0]); 116 117 DeleteCriticalSection(&num_waiters_crit_sect_); 118} 119 120void ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect) { 121 SleepCS(crit_sect, INFINITE); 122} 123 124bool 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 168void 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 179void 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