OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef MOJO_EDK_SYSTEM_WATCHER_H_ | 5 #ifndef MOJO_EDK_SYSTEM_WATCHER_H_ |
6 #define MOJO_EDK_SYSTEM_WATCHER_H_ | 6 #define MOJO_EDK_SYSTEM_WATCHER_H_ |
7 | 7 |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
11 #include "base/synchronization/lock.h" | 11 #include "base/synchronization/lock.h" |
| 12 #include "mojo/edk/system/atomic_flag.h" |
12 #include "mojo/public/c/system/functions.h" | 13 #include "mojo/public/c/system/functions.h" |
13 #include "mojo/public/c/system/types.h" | 14 #include "mojo/public/c/system/types.h" |
14 | 15 |
15 namespace mojo { | 16 namespace mojo { |
16 namespace edk { | 17 namespace edk { |
17 | 18 |
18 struct HandleSignalsState; | 19 struct HandleSignalsState; |
19 | 20 |
20 // This object corresponds to a watch added by a single call to |MojoWatch()|. | 21 // This object corresponds to a watcher added by a single call to |
| 22 // |MojoRegisterWatcher()|. |
21 // | 23 // |
22 // An event may occur at any time which should trigger a Watcher to run its | 24 // An event may occur at any time which should trigger a Watcher to run its |
23 // callback, but the callback needs to be deferred until all EDK locks are | 25 // callback, but the callback needs to be deferred until all EDK locks are |
24 // released. At the same time, a watch may be cancelled at any time by | 26 // released. At the same time, a watcher may be unregistered at any time by |
25 // |MojoCancelWatch()| and it is not OK for the callback to be invoked after | 27 // |MojoUnregisterWatcher()| and it is not OK for the callback to be invoked |
26 // that happens. | 28 // after that happens. |
27 // | 29 // |
28 // Therefore a Watcher needs to have some associated thread-safe state to track | 30 // Therefore a Watcher needs to have some associated thread-safe state to track |
29 // its cancellation, which is why it's ref-counted. | 31 // its cancellation, which is why it's ref-counted. |
30 class Watcher : public base::RefCountedThreadSafe<Watcher> { | 32 class Watcher : public base::RefCountedThreadSafe<Watcher> { |
31 public: | 33 public: |
32 using WatchCallback = base::Callback<void(MojoResult, | 34 using WatchCallback = base::Callback<void(MojoResult, |
33 const HandleSignalsState&, | 35 const HandleSignalsState&, |
34 MojoWatchNotificationFlags)>; | 36 MojoWatchNotificationFlags)>; |
35 | 37 |
36 // Constructs a new Watcher which watches for |signals| to be satisfied on a | 38 // Constructs a new Watcher which watches for |signals| to be satisfied on a |
37 // handle and which invokes |callback| either when one such signal is | 39 // handle and which invokes |callback| either when one such signal is |
38 // satisfied, or all such signals become unsatisfiable. | 40 // satisfied, or all such signals become unsatisfiable. |
39 Watcher(MojoHandleSignals signals, const WatchCallback& callback); | 41 Watcher(MojoHandleSignals signals, const WatchCallback& callback); |
40 | 42 |
41 // Runs the Watcher's callback with the given arguments if it hasn't been | 43 // Runs the Watcher's callback with the given arguments if it hasn't been |
42 // cancelled yet. | 44 // cancelled yet. |
43 void MaybeInvokeCallback(MojoResult result, | 45 void MaybeInvokeCallback(MojoResult result, |
44 const HandleSignalsState& state, | 46 const HandleSignalsState& state, |
45 MojoWatchNotificationFlags flags); | 47 MojoWatchNotificationFlags flags); |
46 | 48 |
47 // Notifies the Watcher of a state change. This may result in the Watcher | 49 // Notifies the Watcher of the handle's current signals state. This may result |
48 // adding a finalizer to the current RequestContext to invoke its callback, | 50 // in the Watcher adding a finalizer to the current RequestContext to invoke |
49 // cancellation notwithstanding. | 51 // its callback if the watcher is currently armed and not cancelled by the |
50 void NotifyForStateChange(const HandleSignalsState& signals_state); | 52 // the time the RequestContext is unwound. |
| 53 void NotifyState(const HandleSignalsState& signals_state); |
51 | 54 |
52 // Notifies the Watcher of handle closure. This always results in the Watcher | 55 // Notifies the Watcher of handle closure. This always results in the Watcher |
53 // adding a finalizer to the current RequestContext to invoke its callback, | 56 // adding a finalizer to the current RequestContext to invoke its callback |
54 // cancellation notwithstanding. | 57 // if the watcher has not been cancelled by the time the RequestContextd is |
| 58 // unwound. |
55 void NotifyClosed(); | 59 void NotifyClosed(); |
56 | 60 |
| 61 // Arms the watch, ensuring that any relevant future state changes will elicit |
| 62 // a single new notification. Returns MOJO_RESULT_OK, or some other error |
| 63 // code otherwise. See documentation for the public |MojoArmWatcher()| API for |
| 64 // details. |
| 65 // |
| 66 // |current_state| must reflect the state of the handle at the time of this |
| 67 // call. |
| 68 MojoResult Arm(const HandleSignalsState& current_state); |
| 69 |
57 // Explicitly cancels the watch, guaranteeing that its callback will never be | 70 // Explicitly cancels the watch, guaranteeing that its callback will never be |
58 // be invoked again. | 71 // be invoked again. |
59 void Cancel(); | 72 void Cancel(); |
60 | 73 |
61 private: | 74 private: |
62 friend class base::RefCountedThreadSafe<Watcher>; | 75 friend class base::RefCountedThreadSafe<Watcher>; |
63 | 76 |
64 ~Watcher(); | 77 ~Watcher(); |
65 | 78 |
66 // The set of signals which are watched by this Watcher. | 79 // The set of signals which are watched by this Watcher. |
67 const MojoHandleSignals signals_; | 80 const MojoHandleSignals signals_; |
68 | 81 |
69 // The callback to invoke with a result and signal state any time signals in | 82 // The callback to invoke with a result and signal state any time signals in |
70 // |signals_| are satisfied or become permanently unsatisfiable. | 83 // |signals_| are satisfied or become permanently unsatisfiable. |
71 const WatchCallback callback_; | 84 const WatchCallback callback_; |
72 | 85 |
73 // Guards |is_cancelled_|. | 86 // Tracks whether or not the watcher is armed. |
74 base::Lock lock_; | 87 AtomicFlag is_armed_; |
| 88 |
| 89 // Guards |is_cancelled_| and provides mutual exclusion for the notification |
| 90 // callback and cancellation events. |
| 91 base::Lock notification_lock_; |
75 | 92 |
76 // Indicates whether the watch has been cancelled. A |Watcher| may exist for a | 93 // Indicates whether the watch has been cancelled. A |Watcher| may exist for a |
77 // brief period of time after being cancelled if it's been attached as a | 94 // brief period of time after being cancelled if it's been attached as a |
78 // RequestContext finalizer. In such cases the callback must not be invoked, | 95 // RequestContext finalizer. In such cases the callback must not be invoked, |
79 // hence this flag. | 96 // hence this flag. |
80 bool is_cancelled_ = false; | 97 bool is_cancelled_ = false; |
81 | 98 |
82 DISALLOW_COPY_AND_ASSIGN(Watcher); | 99 DISALLOW_COPY_AND_ASSIGN(Watcher); |
83 }; | 100 }; |
84 | 101 |
85 } // namespace edk | 102 } // namespace edk |
86 } // namespace mojo | 103 } // namespace mojo |
87 | 104 |
88 #endif // MOJO_EDK_SYSTEM_WATCHER_H_ | 105 #endif // MOJO_EDK_SYSTEM_WATCHER_H_ |
OLD | NEW |