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 14namespace base { 15 16WaitableEvent::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 23WaitableEvent::WaitableEvent(HANDLE handle) 24 : handle_(handle) { 25 CHECK(handle_.IsValid()) << "Tried to create WaitableEvent from NULL handle"; 26} 27 28WaitableEvent::~WaitableEvent() { 29} 30 31HANDLE WaitableEvent::Release() { 32 return handle_.Take(); 33} 34 35void WaitableEvent::Reset() { 36 ResetEvent(handle_.Get()); 37} 38 39void WaitableEvent::Signal() { 40 SetEvent(handle_.Get()); 41} 42 43bool WaitableEvent::IsSignaled() { 44 return TimedWait(TimeDelta::FromMilliseconds(0)); 45} 46 47void 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 55bool 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 77size_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