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#ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ 63f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/base_api.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <windows.h> 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX) 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <list> 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <utility> 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h" 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h" 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This replaces INFINITE from Win32 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kNoTimeout = -1; 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass TimeDelta; 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A WaitableEvent can be a useful thread synchronization tool when you want to 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// allow one thread to wait for another thread to finish some work. For 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// non-Windows systems, this can only be used from within a single address 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// space. 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// protect a simple boolean value. However, if you find yourself using a 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// WaitableEvent in conjunction with a Lock to wait for a more complex state 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// change (e.g., for an item to be added to a queue), then you should probably 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// be using a ConditionVariable instead of a WaitableEvent. 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// NOTE: On Windows, this class provides a subset of the functionality afforded 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// by a Windows event object. This is intentional. If you are writing Windows 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// specific code and you need other features of a Windows event, then you might 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// be better off just using an Windows event directly. 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API WaitableEvent { 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If manual_reset is true, then to set the event state to non-signaled, a 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // consumer must call the Reset method. If this parameter is false, then the 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // system automatically resets the event state to non-signaled after a single 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // waiting thread has been released. 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WaitableEvent(bool manual_reset, bool initially_signaled); 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Create a WaitableEvent from an Event HANDLE which has already been 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // created. This objects takes ownership of the HANDLE and will close it when 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // deleted. 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit WaitableEvent(HANDLE event_handle); 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Releases ownership of the handle from this object. 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HANDLE Release(); 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~WaitableEvent(); 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Put the event in the un-signaled state. 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Reset(); 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Put the event in the signaled state. Causing any thread blocked on Wait 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to be woken up. 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Signal(); 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Returns true if the event is in the signaled state, else false. If this 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // is not a manual reset event, then this test will cause a reset. 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool IsSignaled(); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Wait indefinitely for the event to be signaled. Returns true if the event 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // was signaled, else false is returned to indicate that waiting failed. 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool Wait(); 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Wait up until max_time has passed for the event to be signaled. Returns 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // true if the event was signaled. If this method returns false, then it 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // does not necessarily mean that max_time was exceeded. 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool TimedWait(const TimeDelta& max_time); 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HANDLE handle() const { return handle_; } 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Wait, synchronously, on multiple events. 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // waitables: an array of WaitableEvent pointers 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // count: the number of elements in @waitables 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // returns: the index of a WaitableEvent which has been signaled. 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // You MUST NOT delete any of the WaitableEvent objects while this wait is 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // happening. 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static size_t WaitMany(WaitableEvent** waitables, size_t count); 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // For asynchronous waiting, see WaitableEventWatcher 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is a private helper class. It's here because it's used by friends of 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // this class (such as WaitableEventWatcher) to be able to enqueue elements 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // of the wait-list 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott class Waiter { 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Signal the waiter to wake up. 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Consider the case of a Waiter which is in multiple WaitableEvent's 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // wait-lists. Each WaitableEvent is automatic-reset and two of them are 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // signaled at the same time. Now, each will wake only the first waiter in 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the wake-list before resetting. However, if those two waiters happen to 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // be the same object (as can happen if another thread didn't have a chance 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to dequeue the waiter from the other wait-list in time), two auto-resets 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // will have happened, but only one waiter has been signaled! 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Because of this, a Waiter may "reject" a wake by returning false. In 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // this case, the auto-reset WaitableEvent shouldn't act as if anything has 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // been notified. 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual bool Fire(WaitableEvent* signaling_event) = 0; 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Waiters may implement this in order to provide an extra condition for 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // pointers match then this function is called as a final check. See the 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // comments in ~Handle for why. 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual bool Compare(void* tag) = 0; 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected: 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual ~Waiter() {} 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott friend class WaitableEventWatcher; 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HANDLE handle_; 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // On Windows, one can close a HANDLE which is currently being waited on. The 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // MSDN documentation says that the resulting behaviour is 'undefined', but 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // it doesn't crash. However, if we were to include the following members 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // event which gets deleted. This mismatch has bitten us several times now, 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // so we have a kernel of the WaitableEvent, which is reference counted. 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // WaitableEventWatchers may then take a reference and thus match the Windows 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // behaviour. 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct WaitableEventKernel : 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public RefCountedThreadSafe<WaitableEventKernel> { 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick WaitableEventKernel(bool manual_reset, bool initially_signaled); 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual ~WaitableEventKernel(); 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool Dequeue(Waiter* waiter, void* tag); 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Lock lock_; 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const bool manual_reset_; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool signaled_; 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::list<Waiter*> waiters_; 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex; 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // When dealing with arrays of WaitableEvent*, we want to sort by the address 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // of the WaitableEvent in order to have a globally consistent locking order. 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // In that case we keep them, in sorted order, in an array of pairs where the 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // second element is the index of the WaitableEvent in the original, 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // unsorted, array. 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static size_t EnqueueMany(WaiterAndIndex* waitables, 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t count, Waiter* waiter); 1683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool SignalAll(); 1703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool SignalOne(); 1713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen void Enqueue(Waiter* waiter); 1723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen scoped_refptr<WaitableEventKernel> kernel_; 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(WaitableEvent); 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ 182