michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef BASE_WAITABLE_EVENT_WATCHER_H_ michael@0: #define BASE_WAITABLE_EVENT_WATCHER_H_ michael@0: michael@0: #include "build/build_config.h" michael@0: michael@0: #if defined(OS_WIN) michael@0: #include "base/object_watcher.h" michael@0: #else michael@0: #include "base/message_loop.h" michael@0: #include "base/waitable_event.h" michael@0: #endif michael@0: michael@0: namespace base { michael@0: michael@0: class Flag; michael@0: class AsyncWaiter; michael@0: class AsyncCallbackTask; michael@0: class WaitableEvent; michael@0: michael@0: // ----------------------------------------------------------------------------- michael@0: // This class provides a way to wait on a WaitableEvent asynchronously. michael@0: // michael@0: // Each instance of this object can be waiting on a single WaitableEvent. When michael@0: // the waitable event is signaled, a callback is made in the thread of a given michael@0: // MessageLoop. This callback can be deleted by deleting the waiter. michael@0: // michael@0: // Typical usage: michael@0: // michael@0: // class MyClass : public base::WaitableEventWatcher::Delegate { michael@0: // public: michael@0: // void DoStuffWhenSignaled(WaitableEvent *waitable_event) { michael@0: // watcher_.StartWatching(waitable_event, this); michael@0: // } michael@0: // virtual void OnWaitableEventSignaled(WaitableEvent* waitable_event) { michael@0: // // OK, time to do stuff! michael@0: // } michael@0: // private: michael@0: // base::WaitableEventWatcher watcher_; michael@0: // }; michael@0: // michael@0: // In the above example, MyClass wants to "do stuff" when waitable_event michael@0: // becomes signaled. WaitableEventWatcher makes this task easy. When MyClass michael@0: // goes out of scope, the watcher_ will be destroyed, and there is no need to michael@0: // worry about OnWaitableEventSignaled being called on a deleted MyClass michael@0: // pointer. michael@0: // michael@0: // BEWARE: With automatically reset WaitableEvents, a signal may be lost if it michael@0: // occurs just before a WaitableEventWatcher is deleted. There is currently no michael@0: // safe way to stop watching an automatic reset WaitableEvent without possibly michael@0: // missing a signal. michael@0: // michael@0: // NOTE: you /are/ allowed to delete the WaitableEvent while still waiting on michael@0: // it with a Watcher. It will act as if the event was never signaled. michael@0: // ----------------------------------------------------------------------------- michael@0: michael@0: class WaitableEventWatcher michael@0: #if defined(OS_POSIX) michael@0: : public MessageLoop::DestructionObserver michael@0: #endif michael@0: { michael@0: public: michael@0: michael@0: WaitableEventWatcher(); michael@0: ~WaitableEventWatcher(); michael@0: michael@0: class Delegate { michael@0: public: michael@0: virtual ~Delegate() { } michael@0: michael@0: // ------------------------------------------------------------------------- michael@0: // This is called on the MessageLoop thread when WaitableEvent has been michael@0: // signaled. michael@0: // michael@0: // Note: the event may not be signaled by the time that this function is michael@0: // called. This indicates only that it has been signaled at some point in michael@0: // the past. michael@0: // ------------------------------------------------------------------------- michael@0: virtual void OnWaitableEventSignaled(WaitableEvent* waitable_event) = 0; michael@0: }; michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: // When @event is signaled, the given delegate is called on the thread of the michael@0: // current message loop when StartWatching is called. The delegate is not michael@0: // deleted. michael@0: // --------------------------------------------------------------------------- michael@0: bool StartWatching(WaitableEvent* event, Delegate* delegate); michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: // Cancel the current watch. Must be called from the same thread which michael@0: // started the watch. michael@0: // michael@0: // Does nothing if no event is being watched, nor if the watch has completed. michael@0: // The delegate will *not* be called for the current watch after this michael@0: // function returns. Since the delegate runs on the same thread as this michael@0: // function, it cannot be called during this function either. michael@0: // --------------------------------------------------------------------------- michael@0: void StopWatching(); michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: // Return the currently watched event, or NULL if no object is currently being michael@0: // watched. michael@0: // --------------------------------------------------------------------------- michael@0: WaitableEvent* GetWatchedEvent(); michael@0: michael@0: private: michael@0: WaitableEvent* event_; michael@0: michael@0: #if defined(OS_WIN) michael@0: // --------------------------------------------------------------------------- michael@0: // The helper class exists because, if WaitableEventWatcher were to inherit michael@0: // from ObjectWatcher::Delegate, then it couldn't also have an inner class michael@0: // called Delegate (at least on Windows). Thus this object exists to proxy michael@0: // the callback function michael@0: // --------------------------------------------------------------------------- michael@0: class ObjectWatcherHelper : public ObjectWatcher::Delegate { michael@0: public: michael@0: ObjectWatcherHelper(WaitableEventWatcher* watcher); michael@0: michael@0: // ------------------------------------------------------------------------- michael@0: // Implementation of ObjectWatcher::Delegate michael@0: // ------------------------------------------------------------------------- michael@0: void OnObjectSignaled(HANDLE h); michael@0: michael@0: private: michael@0: WaitableEventWatcher *const watcher_; michael@0: }; michael@0: michael@0: void OnObjectSignaled(); michael@0: michael@0: Delegate* delegate_; michael@0: ObjectWatcherHelper helper_; michael@0: ObjectWatcher watcher_; michael@0: #else michael@0: // --------------------------------------------------------------------------- michael@0: // Implementation of MessageLoop::DestructionObserver michael@0: // --------------------------------------------------------------------------- michael@0: void WillDestroyCurrentMessageLoop(); michael@0: michael@0: MessageLoop* message_loop_; michael@0: scoped_refptr cancel_flag_; michael@0: AsyncWaiter* waiter_; michael@0: AsyncCallbackTask* callback_task_; michael@0: scoped_refptr kernel_; michael@0: #endif michael@0: }; michael@0: michael@0: } // namespace base michael@0: michael@0: #endif // BASE_WAITABLE_EVENT_WATCHER_H_