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/threading/thread_restrictions.h" 12 #include "base/time/time.h" 13 14 namespace base { 15 16 WaitableEvent::WaitableEvent(bool manual_reset, bool signaled) 17 : handle_(CreateEvent(NULL, manual_reset, signaled, NULL)) { 18 // We're probably going to crash anyways if this is ever NULL, so we might as 19 // well make our stack reports more informative by crashing here. 20 CHECK(handle_.IsValid()); 21 } 22 23 WaitableEvent::WaitableEvent(HANDLE handle) 24 : handle_(handle) { 25 CHECK(handle_.IsValid()) << "Tried to create WaitableEvent from NULL handle"; 26 } 27 28 WaitableEvent::~WaitableEvent() { 29 } 30 31 HANDLE WaitableEvent::Release() { 32 return handle_.Take(); 33 } 34 35 void WaitableEvent::Reset() { 36 ResetEvent(handle_.Get()); 37 } 38 39 void WaitableEvent::Signal() { 40 SetEvent(handle_.Get()); 41 } 42 43 bool WaitableEvent::IsSignaled() { 44 return TimedWait(TimeDelta::FromMilliseconds(0)); 45 } 46 47 void WaitableEvent::Wait() { 48 base::ThreadRestrictions::AssertWaitAllowed(); 49 DWORD result = WaitForSingleObject(handle_.Get(), INFINITE); 50 // It is most unexpected that this should ever fail. Help consumers learn 51 // about it if it should ever fail. 52 DCHECK_EQ(WAIT_OBJECT_0, result) << "WaitForSingleObject failed"; 53 } 54 55 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { 56 base::ThreadRestrictions::AssertWaitAllowed(); 57 DCHECK(max_time >= TimeDelta::FromMicroseconds(0)); 58 // Be careful here. TimeDelta has a precision of microseconds, but this API 59 // is in milliseconds. If there are 5.5ms left, should the delay be 5 or 6? 60 // It should be 6 to avoid returning too early. 61 double timeout = ceil(max_time.InMillisecondsF()); 62 DWORD result = WaitForSingleObject(handle_.Get(), 63 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 base::ThreadRestrictions::AssertWaitAllowed(); 79 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 80 CHECK_LE(count, MAXIMUM_WAIT_OBJECTS) 81 << "Can only wait on " << MAXIMUM_WAIT_OBJECTS << " with WaitMany"; 82 83 for (size_t i = 0; i < count; ++i) 84 handles[i] = events[i]->handle(); 85 86 // The cast is safe because count is small - see the CHECK above. 87 DWORD result = 88 WaitForMultipleObjects(static_cast<DWORD>(count), 89 handles, 90 FALSE, // don't wait for all the objects 91 INFINITE); // no timeout 92 if (result >= WAIT_OBJECT_0 + count) { 93 DPLOG(FATAL) << "WaitForMultipleObjects failed"; 94 return 0; 95 } 96 97 return result - WAIT_OBJECT_0; 98 } 99 100 } // namespace base 101