• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 MOJO_CORE_WATCH_H_
6 #define MOJO_CORE_WATCH_H_
7 
8 #include "base/macros.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/synchronization/lock.h"
11 #include "mojo/core/atomic_flag.h"
12 #include "mojo/core/handle_signals_state.h"
13 #include "mojo/public/c/system/trap.h"
14 
15 namespace mojo {
16 namespace core {
17 
18 class Dispatcher;
19 class WatcherDispatcher;
20 
21 // Encapsulates the state associated with a single watch context within a
22 // watcher.
23 //
24 // Every Watch has its own cancellation state, and is captured by RequestContext
25 // notification finalizers to avoid redundant context resolution during
26 // finalizer execution.
27 class Watch : public base::RefCountedThreadSafe<Watch> {
28  public:
29   // Constructs a Watch which represents a watch within |watcher| associated
30   // with |context|, watching |dispatcher| for |signals|.
31   Watch(const scoped_refptr<WatcherDispatcher>& watcher,
32         const scoped_refptr<Dispatcher>& dispatcher,
33         uintptr_t context,
34         MojoHandleSignals signals,
35         MojoTriggerCondition condition);
36 
37   // Notifies the Watch of a potential state change.
38   //
39   // If |allowed_to_call_callback| is true, this may add a notification
40   // finalizer to the current RequestContext to invoke the watcher's callback
41   // with this watch's context. See return values below.
42   //
43   // This is called directly by WatcherDispatcher whenever the Watch's observed
44   // dispatcher notifies the WatcherDispatcher of a state change.
45   //
46   // Returns |true| if the Watch entered or remains in a ready state as a result
47   // of the state change. If |allowed_to_call_callback| was true in this case,
48   // the Watch will have also attached a notification finalizer to the current
49   // RequestContext.
50   //
51   // Returns |false| if the
52   bool NotifyState(const HandleSignalsState& state,
53                    bool allowed_to_call_callback);
54 
55   // Notifies the watch of cancellation ASAP. This will always be the last
56   // notification sent for the watch.
57   void Cancel();
58 
59   // Finalizer method for RequestContexts. This method is invoked once for every
60   // notification finalizer added to a RequestContext by this object. This calls
61   // down into the WatcherDispatcher to do the actual notification call.
62   void InvokeCallback(MojoResult result,
63                       const HandleSignalsState& state,
64                       MojoTrapEventFlags flags);
65 
dispatcher()66   const scoped_refptr<Dispatcher>& dispatcher() const { return dispatcher_; }
context()67   uintptr_t context() const { return context_; }
68 
last_known_result()69   MojoResult last_known_result() const {
70     AssertWatcherLockAcquired();
71     return last_known_result_;
72   }
73 
last_known_signals_state()74   MojoHandleSignalsState last_known_signals_state() const {
75     AssertWatcherLockAcquired();
76     return last_known_signals_state_;
77   }
78 
ready()79   bool ready() const {
80     AssertWatcherLockAcquired();
81     return last_known_result_ == MOJO_RESULT_OK ||
82            last_known_result_ == MOJO_RESULT_FAILED_PRECONDITION;
83   }
84 
85  private:
86   friend class base::RefCountedThreadSafe<Watch>;
87 
88   ~Watch();
89 
90 #if DCHECK_IS_ON()
91   void AssertWatcherLockAcquired() const;
92 #else
AssertWatcherLockAcquired()93   void AssertWatcherLockAcquired() const {}
94 #endif
95 
96   const scoped_refptr<WatcherDispatcher> watcher_;
97   const scoped_refptr<Dispatcher> dispatcher_;
98   const uintptr_t context_;
99   const MojoHandleSignals signals_;
100   const MojoTriggerCondition condition_;
101 
102   // The result code with which this Watch would notify if currently armed,
103   // based on the last known signaling state of |dispatcher_|. Guarded by the
104   // owning WatcherDispatcher's lock.
105   MojoResult last_known_result_ = MOJO_RESULT_UNKNOWN;
106 
107   // The last known signaling state of |dispatcher_|. Guarded by the owning
108   // WatcherDispatcher's lock.
109   MojoHandleSignalsState last_known_signals_state_ = {0, 0};
110 
111   // Guards |is_cancelled_| below and mutually excludes individual watch
112   // notification executions for this same watch context.
113   //
114   // Note that this should only be acquired from a RequestContext finalizer to
115   // ensure that no other internal locks are already held.
116   base::Lock notification_lock_;
117 
118   // Guarded by |notification_lock_|.
119   bool is_cancelled_ = false;
120 
121   DISALLOW_COPY_AND_ASSIGN(Watch);
122 };
123 
124 }  // namespace core
125 }  // namespace mojo
126 
127 #endif  // MOJO_CORE_WATCH_H_
128