1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_ 6 #define BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_ 7 8 #include "base/base_export.h" 9 #include "base/macros.h" 10 #include "base/sequenced_task_runner.h" 11 #include "build/build_config.h" 12 13 #if defined(OS_WIN) 14 #include "base/win/object_watcher.h" 15 #include "base/win/scoped_handle.h" 16 #elif defined(OS_MACOSX) 17 #include <dispatch/dispatch.h> 18 19 #include "base/mac/scoped_dispatch_object.h" 20 #include "base/memory/weak_ptr.h" 21 #include "base/synchronization/waitable_event.h" 22 #else 23 #include "base/sequence_checker.h" 24 #include "base/synchronization/waitable_event.h" 25 #endif 26 27 #if !defined(OS_WIN) 28 #include "base/callback.h" 29 #endif 30 31 namespace base { 32 33 class Flag; 34 class AsyncWaiter; 35 class WaitableEvent; 36 37 // This class provides a way to wait on a WaitableEvent asynchronously. 38 // 39 // Each instance of this object can be waiting on a single WaitableEvent. When 40 // the waitable event is signaled, a callback is invoked on the sequence that 41 // called StartWatching(). This callback can be deleted by deleting the waiter. 42 // 43 // Typical usage: 44 // 45 // class MyClass { 46 // public: 47 // void DoStuffWhenSignaled(WaitableEvent *waitable_event) { 48 // watcher_.StartWatching(waitable_event, 49 // base::BindOnce(&MyClass::OnWaitableEventSignaled, this); 50 // } 51 // private: 52 // void OnWaitableEventSignaled(WaitableEvent* waitable_event) { 53 // // OK, time to do stuff! 54 // } 55 // base::WaitableEventWatcher watcher_; 56 // }; 57 // 58 // In the above example, MyClass wants to "do stuff" when waitable_event 59 // becomes signaled. WaitableEventWatcher makes this task easy. When MyClass 60 // goes out of scope, the watcher_ will be destroyed, and there is no need to 61 // worry about OnWaitableEventSignaled being called on a deleted MyClass 62 // pointer. 63 // 64 // BEWARE: With automatically reset WaitableEvents, a signal may be lost if it 65 // occurs just before a WaitableEventWatcher is deleted. There is currently no 66 // safe way to stop watching an automatic reset WaitableEvent without possibly 67 // missing a signal. 68 // 69 // NOTE: you /are/ allowed to delete the WaitableEvent while still waiting on 70 // it with a Watcher. But pay attention: if the event was signaled and deleted 71 // right after, the callback may be called with deleted WaitableEvent pointer. 72 73 class BASE_EXPORT WaitableEventWatcher 74 #if defined(OS_WIN) 75 : public win::ObjectWatcher::Delegate 76 #endif 77 { 78 public: 79 using EventCallback = OnceCallback<void(WaitableEvent*)>; 80 81 WaitableEventWatcher(); 82 83 #if defined(OS_WIN) 84 ~WaitableEventWatcher() override; 85 #else 86 ~WaitableEventWatcher(); 87 #endif 88 89 // When |event| is signaled, |callback| is called on the sequence that called 90 // StartWatching(). 91 // |task_runner| is used for asynchronous executions of calling |callback|. 92 bool StartWatching(WaitableEvent* event, 93 EventCallback callback, 94 scoped_refptr<SequencedTaskRunner> task_runner); 95 96 // Cancel the current watch. Must be called from the same sequence which 97 // started the watch. 98 // 99 // Does nothing if no event is being watched, nor if the watch has completed. 100 // The callback will *not* be called for the current watch after this 101 // function returns. Since the callback runs on the same sequence as this 102 // function, it cannot be called during this function either. 103 void StopWatching(); 104 105 private: 106 #if defined(OS_WIN) 107 void OnObjectSignaled(HANDLE h) override; 108 109 // Duplicated handle of the event passed to StartWatching(). 110 win::ScopedHandle duplicated_event_handle_; 111 112 // A watcher for |duplicated_event_handle_|. The handle MUST outlive 113 // |watcher_|. 114 win::ObjectWatcher watcher_; 115 116 EventCallback callback_; 117 WaitableEvent* event_ = nullptr; 118 #elif defined(OS_MACOSX) 119 // Invokes the callback and resets the source. Must be called on the task 120 // runner on which StartWatching() was called. 121 void InvokeCallback(); 122 123 // Closure bound to the event being watched. This will be is_null() if 124 // nothing is being watched. 125 OnceClosure callback_; 126 127 // A reference to the receive right that is kept alive while a watcher 128 // is waiting. Null if no event is being watched. 129 scoped_refptr<WaitableEvent::ReceiveRight> receive_right_; 130 131 // A TYPE_MACH_RECV dispatch source on |receive_right_|. When a receive event 132 // is delivered, the message queue will be peeked and the bound |callback_| 133 // may be run. This will be null if nothing is currently being watched. 134 ScopedDispatchObject<dispatch_source_t> source_; 135 136 // Used to vend a weak pointer for calling InvokeCallback() from the 137 // |source_| event handler. 138 WeakPtrFactory<WaitableEventWatcher> weak_ptr_factory_; 139 #else 140 // Instantiated in StartWatching(). Set before the callback runs. Reset in 141 // StopWatching() or StartWatching(). 142 scoped_refptr<Flag> cancel_flag_; 143 144 // Enqueued in the wait list of the watched WaitableEvent. 145 AsyncWaiter* waiter_ = nullptr; 146 147 // Kernel of the watched WaitableEvent. 148 scoped_refptr<WaitableEvent::WaitableEventKernel> kernel_; 149 150 // Ensures that StartWatching() and StopWatching() are called on the same 151 // sequence. 152 SequenceChecker sequence_checker_; 153 #endif 154 155 DISALLOW_COPY_AND_ASSIGN(WaitableEventWatcher); 156 }; 157 158 } // namespace base 159 160 #endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_ 161