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