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