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