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_); 21} 22 23WaitableEvent::WaitableEvent(HANDLE handle) 24 : handle_(handle) { 25 CHECK(handle) << "Tried to create WaitableEvent from NULL handle"; 26} 27 28WaitableEvent::~WaitableEvent() { 29 CloseHandle(handle_); 30} 31 32HANDLE WaitableEvent::Release() { 33 HANDLE rv = handle_; 34 handle_ = INVALID_HANDLE_VALUE; 35 return rv; 36} 37 38void WaitableEvent::Reset() { 39 ResetEvent(handle_); 40} 41 42void WaitableEvent::Signal() { 43 SetEvent(handle_); 44} 45 46bool WaitableEvent::IsSignaled() { 47 return TimedWait(TimeDelta::FromMilliseconds(0)); 48} 49 50void WaitableEvent::Wait() { 51 base::ThreadRestrictions::AssertWaitAllowed(); 52 DWORD result = WaitForSingleObject(handle_, INFINITE); 53 // It is most unexpected that this should ever fail. Help consumers learn 54 // about it if it should ever fail. 55 DCHECK_EQ(WAIT_OBJECT_0, result) << "WaitForSingleObject failed"; 56} 57 58bool WaitableEvent::TimedWait(const TimeDelta& max_time) { 59 base::ThreadRestrictions::AssertWaitAllowed(); 60 DCHECK(max_time >= TimeDelta::FromMicroseconds(0)); 61 // Be careful here. TimeDelta has a precision of microseconds, but this API 62 // is in milliseconds. If there are 5.5ms left, should the delay be 5 or 6? 63 // It should be 6 to avoid returning too early. 64 double timeout = ceil(max_time.InMillisecondsF()); 65 DWORD result = WaitForSingleObject(handle_, static_cast<DWORD>(timeout)); 66 switch (result) { 67 case WAIT_OBJECT_0: 68 return true; 69 case WAIT_TIMEOUT: 70 return false; 71 } 72 // It is most unexpected that this should ever fail. Help consumers learn 73 // about it if it should ever fail. 74 NOTREACHED() << "WaitForSingleObject failed"; 75 return false; 76} 77 78// static 79size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) { 80 base::ThreadRestrictions::AssertWaitAllowed(); 81 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 82 CHECK_LE(count, MAXIMUM_WAIT_OBJECTS) 83 << "Can only wait on " << MAXIMUM_WAIT_OBJECTS << " with WaitMany"; 84 85 for (size_t i = 0; i < count; ++i) 86 handles[i] = events[i]->handle(); 87 88 // The cast is safe because count is small - see the CHECK above. 89 DWORD result = 90 WaitForMultipleObjects(static_cast<DWORD>(count), 91 handles, 92 FALSE, // don't wait for all the objects 93 INFINITE); // no timeout 94 if (result >= WAIT_OBJECT_0 + count) { 95 DLOG_GETLASTERROR(FATAL) << "WaitForMultipleObjects failed"; 96 return 0; 97 } 98 99 return result - WAIT_OBJECT_0; 100} 101 102} // namespace base 103