15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/object_watcher.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Flag; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AsyncWaiter; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AsyncCallbackTask; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WaitableEvent; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class provides a way to wait on a WaitableEvent asynchronously. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Each instance of this object can be waiting on a single WaitableEvent. When 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the waitable event is signaled, a callback is made in the thread of a given 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessageLoop. This callback can be deleted by deleting the waiter. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Typical usage: 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// class MyClass { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// public: 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// void DoStuffWhenSignaled(WaitableEvent *waitable_event) { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// watcher_.StartWatching(waitable_event, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// base::Bind(&MyClass::OnWaitableEventSignaled, this); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// private: 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// void OnWaitableEventSignaled(WaitableEvent* waitable_event) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // OK, time to do stuff! 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base::WaitableEventWatcher watcher_; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// }; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the above example, MyClass wants to "do stuff" when waitable_event 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// becomes signaled. WaitableEventWatcher makes this task easy. When MyClass 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// goes out of scope, the watcher_ will be destroyed, and there is no need to 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// worry about OnWaitableEventSignaled being called on a deleted MyClass 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pointer. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BEWARE: With automatically reset WaitableEvents, a signal may be lost if it 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// occurs just before a WaitableEventWatcher is deleted. There is currently no 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// safe way to stop watching an automatic reset WaitableEvent without possibly 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// missing a signal. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: you /are/ allowed to delete the WaitableEvent while still waiting on 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it with a Watcher. It will act as if the event was never signaled. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT WaitableEventWatcher 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : public win::ObjectWatcher::Delegate { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : public MessageLoop::DestructionObserver { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef Callback<void(WaitableEvent*)> EventCallback; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEventWatcher(); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~WaitableEventWatcher(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // When @event is signaled, the given callback is called on the thread of the 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // current message loop when StartWatching is called. 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool StartWatching(WaitableEvent* event, const EventCallback& callback); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel the current watch. Must be called from the same thread which 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // started the watch. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Does nothing if no event is being watched, nor if the watch has completed. 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The callback will *not* be called for the current watch after this 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // function returns. Since the callback runs on the same thread as this 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function, it cannot be called during this function either. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopWatching(); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return the currently watched event, or NULL if no object is currently being 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // watched. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* GetWatchedEvent(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Return the callback that will be invoked when the event is 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // signaled. 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const EventCallback& callback() const { return callback_; } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnObjectSignaled(HANDLE h) OVERRIDE; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win::ObjectWatcher watcher_; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Implementation of MessageLoop::DestructionObserver 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void WillDestroyCurrentMessageLoop() OVERRIDE; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessageLoop* message_loop_; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<Flag> cancel_flag_; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsyncWaiter* waiter_; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Closure internal_callback_; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<WaitableEvent::WaitableEventKernel> kernel_; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* event_; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EventCallback callback_; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_WATCHER_H_ 115