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_WATCHER_H_ 63f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "build/build_config.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/win/object_watcher.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h" 153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/synchronization/waitable_event.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/base_api.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass Flag; 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass AsyncWaiter; 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass AsyncCallbackTask; 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass WaitableEvent; 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ----------------------------------------------------------------------------- 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class provides a way to wait on a WaitableEvent asynchronously. 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Each instance of this object can be waiting on a single WaitableEvent. When 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the waitable event is signaled, a callback is made in the thread of a given 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// MessageLoop. This callback can be deleted by deleting the waiter. 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Typical usage: 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// class MyClass : public base::WaitableEventWatcher::Delegate { 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// public: 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// void DoStuffWhenSignaled(WaitableEvent *waitable_event) { 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// watcher_.StartWatching(waitable_event, this); 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// } 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// virtual void OnWaitableEventSignaled(WaitableEvent* waitable_event) { 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// // OK, time to do stuff! 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// } 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// private: 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// base::WaitableEventWatcher watcher_; 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// }; 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// In the above example, MyClass wants to "do stuff" when waitable_event 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// becomes signaled. WaitableEventWatcher makes this task easy. When MyClass 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// goes out of scope, the watcher_ will be destroyed, and there is no need to 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// worry about OnWaitableEventSignaled being called on a deleted MyClass 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// pointer. 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// BEWARE: With automatically reset WaitableEvents, a signal may be lost if it 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// occurs just before a WaitableEventWatcher is deleted. There is currently no 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// safe way to stop watching an automatic reset WaitableEvent without possibly 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// missing a signal. 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// NOTE: you /are/ allowed to delete the WaitableEvent while still waiting on 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// it with a Watcher. It will act as if the event was never signaled. 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ----------------------------------------------------------------------------- 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API WaitableEventWatcher 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX) 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : public MessageLoop::DestructionObserver 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WaitableEventWatcher(); 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~WaitableEventWatcher(); 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott class Delegate { 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual ~Delegate() { } 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ------------------------------------------------------------------------- 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is called on the MessageLoop thread when WaitableEvent has been 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // signaled. 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note: the event may not be signaled by the time that this function is 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // called. This indicates only that it has been signaled at some point in 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the past. 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ------------------------------------------------------------------------- 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnWaitableEventSignaled(WaitableEvent* waitable_event) = 0; 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // When @event is signaled, the given delegate is called on the thread of the 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // current message loop when StartWatching is called. The delegate is not 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // deleted. 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool StartWatching(WaitableEvent* event, Delegate* delegate); 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Cancel the current watch. Must be called from the same thread which 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // started the watch. 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Does nothing if no event is being watched, nor if the watch has completed. 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The delegate will *not* be called for the current watch after this 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // function returns. Since the delegate runs on the same thread as this 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // function, it cannot be called during this function either. 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void StopWatching(); 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Return the currently watched event, or NULL if no object is currently being 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // watched. 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WaitableEvent* GetWatchedEvent(); 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Return the delegate, or NULL if there is no delegate. 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Delegate* delegate() { 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return delegate_; 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The helper class exists because, if WaitableEventWatcher were to inherit 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // from ObjectWatcher::Delegate, then it couldn't also have an inner class 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // called Delegate (at least on Windows). Thus this object exists to proxy 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the callback function 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 1273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen class ObjectWatcherHelper : public win::ObjectWatcher::Delegate { 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ObjectWatcherHelper(WaitableEventWatcher* watcher); 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ------------------------------------------------------------------------- 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Implementation of ObjectWatcher::Delegate 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ------------------------------------------------------------------------- 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void OnObjectSignaled(HANDLE h); 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WaitableEventWatcher *const watcher_; 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void OnObjectSignaled(); 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ObjectWatcherHelper helper_; 1433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen win::ObjectWatcher watcher_; 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Implementation of MessageLoop::DestructionObserver 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --------------------------------------------------------------------------- 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual void WillDestroyCurrentMessageLoop(); 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop* message_loop_; 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<Flag> cancel_flag_; 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AsyncWaiter* waiter_; 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AsyncCallbackTask* callback_task_; 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<WaitableEvent::WaitableEventKernel> kernel_; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen WaitableEvent* event_; 1583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Delegate* delegate_; 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_ 165