Home | History | Annotate | Download | only in core
      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 
     66   const scoped_refptr<Dispatcher>& dispatcher() const { return dispatcher_; }
     67   uintptr_t context() const { return context_; }
     68 
     69   MojoResult last_known_result() const {
     70     AssertWatcherLockAcquired();
     71     return last_known_result_;
     72   }
     73 
     74   MojoHandleSignalsState last_known_signals_state() const {
     75     AssertWatcherLockAcquired();
     76     return last_known_signals_state_;
     77   }
     78 
     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
     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