1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/synchronization/waitable_event.h" 6 7 #include <math.h> 8 #include <windows.h> 9 10 #include "base/logging.h" 11 #include "base/time.h" 12 13 namespace base { 14 15 WaitableEvent::WaitableEvent(bool manual_reset, bool signaled) 16 : handle_(CreateEvent(NULL, manual_reset, signaled, NULL)) { 17 // We're probably going to crash anyways if this is ever NULL, so we might as 18 // well make our stack reports more informative by crashing here. 19 CHECK(handle_); 20 } 21 22 WaitableEvent::WaitableEvent(HANDLE handle) 23 : handle_(handle) { 24 CHECK(handle) << "Tried to create WaitableEvent from NULL handle"; 25 } 26 27 WaitableEvent::~WaitableEvent() { 28 CloseHandle(handle_); 29 } 30 31 HANDLE WaitableEvent::Release() { 32 HANDLE rv = handle_; 33 handle_ = INVALID_HANDLE_VALUE; 34 return rv; 35 } 36 37 void WaitableEvent::Reset() { 38 ResetEvent(handle_); 39 } 40 41 void WaitableEvent::Signal() { 42 SetEvent(handle_); 43 } 44 45 bool WaitableEvent::IsSignaled() { 46 return TimedWait(TimeDelta::FromMilliseconds(0)); 47 } 48 49 bool WaitableEvent::Wait() { 50 DWORD result = WaitForSingleObject(handle_, INFINITE); 51 // It is most unexpected that this should ever fail. Help consumers learn 52 // about it if it should ever fail. 53 DCHECK_EQ(WAIT_OBJECT_0, result) << "WaitForSingleObject failed"; 54 return result == WAIT_OBJECT_0; 55 } 56 57 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { 58 DCHECK(max_time >= TimeDelta::FromMicroseconds(0)); 59 // Be careful here. TimeDelta has a precision of microseconds, but this API 60 // is in milliseconds. If there are 5.5ms left, should the delay be 5 or 6? 61 // It should be 6 to avoid returning too early. 62 double timeout = ceil(max_time.InMillisecondsF()); 63 DWORD result = WaitForSingleObject(handle_, static_cast<DWORD>(timeout)); 64 switch (result) { 65 case WAIT_OBJECT_0: 66 return true; 67 case WAIT_TIMEOUT: 68 return false; 69 } 70 // It is most unexpected that this should ever fail. Help consumers learn 71 // about it if it should ever fail. 72 NOTREACHED() << "WaitForSingleObject failed"; 73 return false; 74 } 75 76 // static 77 size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) { 78 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 79 CHECK_LE(count, MAXIMUM_WAIT_OBJECTS) 80 << "Can only wait on " << MAXIMUM_WAIT_OBJECTS << " with WaitMany"; 81 82 for (size_t i = 0; i < count; ++i) 83 handles[i] = events[i]->handle(); 84 85 // The cast is safe because count is small - see the CHECK above. 86 DWORD result = 87 WaitForMultipleObjects(static_cast<DWORD>(count), 88 handles, 89 FALSE, // don't wait for all the objects 90 INFINITE); // no timeout 91 if (result >= WAIT_OBJECT_0 + count) { 92 NOTREACHED() << "WaitForMultipleObjects failed: " << GetLastError(); 93 return 0; 94 } 95 96 return result - WAIT_OBJECT_0; 97 } 98 99 } // namespace base 100