1// Copyright (c) 2006-2008 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/waitable_event.h" 6 7#include <math.h> 8#include <windows.h> 9 10#include "base/logging.h" 11#include "base/time.h" 12 13namespace base { 14 15WaitableEvent::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 22WaitableEvent::WaitableEvent(HANDLE handle) 23 : handle_(handle) { 24 CHECK(handle) << "Tried to create WaitableEvent from NULL handle"; 25} 26 27WaitableEvent::~WaitableEvent() { 28 CloseHandle(handle_); 29} 30 31HANDLE WaitableEvent::Release() { 32 HANDLE rv = handle_; 33 handle_ = INVALID_HANDLE_VALUE; 34 return rv; 35} 36 37void WaitableEvent::Reset() { 38 ResetEvent(handle_); 39} 40 41void WaitableEvent::Signal() { 42 SetEvent(handle_); 43} 44 45bool WaitableEvent::IsSignaled() { 46 return TimedWait(TimeDelta::FromMilliseconds(0)); 47} 48 49bool 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(result == WAIT_OBJECT_0) << "WaitForSingleObject failed"; 54 return result == WAIT_OBJECT_0; 55} 56 57bool 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 77size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) { 78 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 79 CHECK(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