1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/waitable_event.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,180 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#ifndef BASE_WAITABLE_EVENT_H_ 1.9 +#define BASE_WAITABLE_EVENT_H_ 1.10 + 1.11 +#include "base/basictypes.h" 1.12 + 1.13 +#if defined(OS_WIN) 1.14 +#include <windows.h> 1.15 +#endif 1.16 + 1.17 +#if defined(OS_POSIX) 1.18 +#include <list> 1.19 +#include <utility> 1.20 +#include "base/condition_variable.h" 1.21 +#include "base/lock.h" 1.22 +#include "base/ref_counted.h" 1.23 +#endif 1.24 + 1.25 +#include "base/message_loop.h" 1.26 + 1.27 +namespace base { 1.28 + 1.29 +// This replaces INFINITE from Win32 1.30 +static const int kNoTimeout = -1; 1.31 + 1.32 +class TimeDelta; 1.33 + 1.34 +// A WaitableEvent can be a useful thread synchronization tool when you want to 1.35 +// allow one thread to wait for another thread to finish some work. For 1.36 +// non-Windows systems, this can only be used from within a single address 1.37 +// space. 1.38 +// 1.39 +// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to 1.40 +// protect a simple boolean value. However, if you find yourself using a 1.41 +// WaitableEvent in conjunction with a Lock to wait for a more complex state 1.42 +// change (e.g., for an item to be added to a queue), then you should probably 1.43 +// be using a ConditionVariable instead of a WaitableEvent. 1.44 +// 1.45 +// NOTE: On Windows, this class provides a subset of the functionality afforded 1.46 +// by a Windows event object. This is intentional. If you are writing Windows 1.47 +// specific code and you need other features of a Windows event, then you might 1.48 +// be better off just using an Windows event directly. 1.49 +class WaitableEvent { 1.50 + public: 1.51 + // If manual_reset is true, then to set the event state to non-signaled, a 1.52 + // consumer must call the Reset method. If this parameter is false, then the 1.53 + // system automatically resets the event state to non-signaled after a single 1.54 + // waiting thread has been released. 1.55 + WaitableEvent(bool manual_reset, bool initially_signaled); 1.56 + 1.57 +#if defined(OS_WIN) 1.58 + // Create a WaitableEvent from an Event HANDLE which has already been 1.59 + // created. This objects takes ownership of the HANDLE and will close it when 1.60 + // deleted. 1.61 + explicit WaitableEvent(HANDLE event_handle); 1.62 + 1.63 + // Releases ownership of the handle from this object. 1.64 + HANDLE Release(); 1.65 +#endif 1.66 + 1.67 + ~WaitableEvent(); 1.68 + 1.69 + // Put the event in the un-signaled state. 1.70 + void Reset(); 1.71 + 1.72 + // Put the event in the signaled state. Causing any thread blocked on Wait 1.73 + // to be woken up. 1.74 + void Signal(); 1.75 + 1.76 + // Returns true if the event is in the signaled state, else false. If this 1.77 + // is not a manual reset event, then this test will cause a reset. 1.78 + bool IsSignaled(); 1.79 + 1.80 + // Wait indefinitely for the event to be signaled. Returns true if the event 1.81 + // was signaled, else false is returned to indicate that waiting failed. 1.82 + bool Wait(); 1.83 + 1.84 + // Wait up until max_time has passed for the event to be signaled. Returns 1.85 + // true if the event was signaled. If this method returns false, then it 1.86 + // does not necessarily mean that max_time was exceeded. 1.87 + bool TimedWait(const TimeDelta& max_time); 1.88 + 1.89 +#if defined(OS_WIN) 1.90 + HANDLE handle() const { return handle_; } 1.91 +#endif 1.92 + 1.93 + // Wait, synchronously, on multiple events. 1.94 + // waitables: an array of WaitableEvent pointers 1.95 + // count: the number of elements in @waitables 1.96 + // 1.97 + // returns: the index of a WaitableEvent which has been signaled. 1.98 + // 1.99 + // You MUST NOT delete any of the WaitableEvent objects while this wait is 1.100 + // happening. 1.101 + static size_t WaitMany(WaitableEvent** waitables, size_t count); 1.102 + 1.103 + // For asynchronous waiting, see WaitableEventWatcher 1.104 + 1.105 + // This is a private helper class. It's here because it's used by friends of 1.106 + // this class (such as WaitableEventWatcher) to be able to enqueue elements 1.107 + // of the wait-list 1.108 + class Waiter { 1.109 + public: 1.110 + // Signal the waiter to wake up. 1.111 + // 1.112 + // Consider the case of a Waiter which is in multiple WaitableEvent's 1.113 + // wait-lists. Each WaitableEvent is automatic-reset and two of them are 1.114 + // signaled at the same time. Now, each will wake only the first waiter in 1.115 + // the wake-list before resetting. However, if those two waiters happen to 1.116 + // be the same object (as can happen if another thread didn't have a chance 1.117 + // to dequeue the waiter from the other wait-list in time), two auto-resets 1.118 + // will have happened, but only one waiter has been signaled! 1.119 + // 1.120 + // Because of this, a Waiter may "reject" a wake by returning false. In 1.121 + // this case, the auto-reset WaitableEvent shouldn't act as if anything has 1.122 + // been notified. 1.123 + virtual bool Fire(WaitableEvent* signaling_event) = 0; 1.124 + 1.125 + // Waiters may implement this in order to provide an extra condition for 1.126 + // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the 1.127 + // pointers match then this function is called as a final check. See the 1.128 + // comments in ~Handle for why. 1.129 + virtual bool Compare(void* tag) = 0; 1.130 + }; 1.131 + 1.132 + private: 1.133 + friend class WaitableEventWatcher; 1.134 + 1.135 +#if defined(OS_WIN) 1.136 + HANDLE handle_; 1.137 +#else 1.138 + // On Windows, one can close a HANDLE which is currently being waited on. The 1.139 + // MSDN documentation says that the resulting behaviour is 'undefined', but 1.140 + // it doesn't crash. However, if we were to include the following members 1.141 + // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an 1.142 + // event which gets deleted. This mismatch has bitten us several times now, 1.143 + // so we have a kernel of the WaitableEvent, which is reference counted. 1.144 + // WaitableEventWatchers may then take a reference and thus match the Windows 1.145 + // behaviour. 1.146 + struct WaitableEventKernel : 1.147 + public RefCountedThreadSafe<WaitableEventKernel> { 1.148 + public: 1.149 + WaitableEventKernel(bool manual_reset, bool initially_signaled) 1.150 + : manual_reset_(manual_reset), 1.151 + signaled_(initially_signaled) { 1.152 + } 1.153 + 1.154 + bool Dequeue(Waiter* waiter, void* tag); 1.155 + 1.156 + Lock lock_; 1.157 + const bool manual_reset_; 1.158 + bool signaled_; 1.159 + std::list<Waiter*> waiters_; 1.160 + }; 1.161 + 1.162 + scoped_refptr<WaitableEventKernel> kernel_; 1.163 + 1.164 + bool SignalAll(); 1.165 + bool SignalOne(); 1.166 + void Enqueue(Waiter* waiter); 1.167 + 1.168 + // When dealing with arrays of WaitableEvent*, we want to sort by the address 1.169 + // of the WaitableEvent in order to have a globally consistent locking order. 1.170 + // In that case we keep them, in sorted order, in an array of pairs where the 1.171 + // second element is the index of the WaitableEvent in the original, 1.172 + // unsorted, array. 1.173 + typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex; 1.174 + static size_t EnqueueMany(WaiterAndIndex* waitables, 1.175 + size_t count, Waiter* waiter); 1.176 +#endif 1.177 + 1.178 + DISALLOW_COPY_AND_ASSIGN(WaitableEvent); 1.179 +}; 1.180 + 1.181 +} // namespace base 1.182 + 1.183 +#endif // BASE_WAITABLE_EVENT_H_