15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WaitableEvent::WaitableEvent(bool manual_reset, bool signaled) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : handle_(CreateEvent(NULL, manual_reset, signaled, NULL)) { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're probably going to crash anyways if this is ever NULL, so we might as 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // well make our stack reports more informative by crashing here. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(handle_); 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WaitableEvent::WaitableEvent(HANDLE handle) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : handle_(handle) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(handle) << "Tried to create WaitableEvent from NULL handle"; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WaitableEvent::~WaitableEvent() { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(handle_); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HANDLE WaitableEvent::Release() { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE rv = handle_; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_ = INVALID_HANDLE_VALUE; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WaitableEvent::Reset() { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResetEvent(handle_); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WaitableEvent::Signal() { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetEvent(handle_); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WaitableEvent::IsSignaled() { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TimedWait(TimeDelta::FromMilliseconds(0)); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WaitableEvent::Wait() { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertWaitAllowed(); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD result = WaitForSingleObject(handle_, INFINITE); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is most unexpected that this should ever fail. Help consumers learn 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // about it if it should ever fail. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(WAIT_OBJECT_0, result) << "WaitForSingleObject failed"; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WaitableEvent::TimedWait(const TimeDelta& max_time) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertWaitAllowed(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(max_time >= TimeDelta::FromMicroseconds(0)); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Be careful here. TimeDelta has a precision of microseconds, but this API 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is in milliseconds. If there are 5.5ms left, should the delay be 5 or 6? 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It should be 6 to avoid returning too early. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double timeout = ceil(max_time.InMillisecondsF()); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD result = WaitForSingleObject(handle_, static_cast<DWORD>(timeout)); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (result) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WAIT_OBJECT_0: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WAIT_TIMEOUT: 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is most unexpected that this should ever fail. Help consumers learn 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // about it if it should ever fail. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "WaitForSingleObject failed"; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::AssertWaitAllowed(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LE(count, MAXIMUM_WAIT_OBJECTS) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Can only wait on " << MAXIMUM_WAIT_OBJECTS << " with WaitMany"; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < count; ++i) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handles[i] = events[i]->handle(); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The cast is safe because count is small - see the CHECK above. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD result = 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitForMultipleObjects(static_cast<DWORD>(count), 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handles, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FALSE, // don't wait for all the objects 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INFINITE); // no timeout 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result >= WAIT_OBJECT_0 + count) { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DLOG_GETLASTERROR(FATAL) << "WaitForMultipleObjects failed"; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result - WAIT_OBJECT_0; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 103