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