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