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