Chromium Code Reviews| Index: mojo/edk/system/watch.h |
| diff --git a/mojo/edk/system/watch.h b/mojo/edk/system/watch.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2e7314c658606895490d6809363a986b816d6af7 |
| --- /dev/null |
| +++ b/mojo/edk/system/watch.h |
| @@ -0,0 +1,124 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef MOJO_EDK_SYSTEM_WATCH_H_ |
| +#define MOJO_EDK_SYSTEM_WATCH_H_ |
| + |
| +#include "base/macros.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "base/synchronization/lock.h" |
| +#include "mojo/edk/system/atomic_flag.h" |
| +#include "mojo/edk/system/handle_signals_state.h" |
| + |
| +namespace mojo { |
| +namespace edk { |
| + |
| +class Dispatcher; |
| +class WatcherDispatcher; |
| + |
| +// Encapsulates the state associated with a single watch context within a |
| +// watcher. |
| +// |
| +// Every Watch has its own cancellation state, and is captured by RequestContext |
| +// notification finalizers to avoid redundant context resolution during |
| +// finalizer execution. |
| +class Watch : public base::RefCountedThreadSafe<Watch> { |
| + public: |
| + // Constructs a Watch which represents a watch within |watcher| associated |
| + // with |context|, watching |dispatcher| for |signals|. |
| + Watch(const scoped_refptr<WatcherDispatcher>& watcher, |
| + const scoped_refptr<Dispatcher>& dispatcher, |
| + uintptr_t context, |
| + MojoHandleSignals signals); |
| + |
| + // Notifies the Watch of a potential state change. |
| + // |
| + // If |allowed_to_call_callback| is true, this may add a notification |
| + // finalizer to the current RequestContext to invoke the watcher's callback |
| + // with this watch's context. See return values below. |
| + // |
| + // This is called directly by WatcherDispatcher whenever the Watch's observed |
| + // dispatcher notifies the WatcherDispatcher of a state change a state change. |
|
yzshen1
2017/03/13 20:21:18
nit: "a state change" occurs twice.
Ken Rockot(use gerrit already)
2017/03/13 22:00:10
Fixed
|
| + // |
| + // Returns |true| if the Watch entered or remains in a ready state as a result |
| + // of the state change. If |allowed_to_call_callback| was true in this case, |
| + // the Watch will have also attached a notification finalizer to the current |
| + // RequestContext. |
| + // |
| + // Returns |false| if the |
| + bool NotifyState(const HandleSignalsState& state, |
| + bool allowed_to_call_callback); |
| + |
| + // Notifies the watch of cancellation ASAP. This will always be the last |
| + // notification sent for the watch. |
| + void Cancel(); |
| + |
| + // Finalizer method for RequestContexts. This method is invoked once for every |
| + // notification finalizer added to a RequestContext by this object. This calls |
| + // down into the WatcherDispatcher to do the actual notification call. |
| + void InvokeCallback(MojoResult result, |
| + const HandleSignalsState& state, |
| + MojoWatcherNotificationFlags flags); |
| + |
| + const scoped_refptr<Dispatcher>& dispatcher() const { return dispatcher_; } |
| + uintptr_t context() const { return context_; } |
| + |
| + MojoResult last_known_result() const { |
| + AssertWatcherLockAcquired(); |
| + return last_known_result_; |
| + } |
| + |
| + MojoHandleSignalsState last_known_signals_state() const { |
| + AssertWatcherLockAcquired(); |
| + return last_known_signals_state_; |
| + } |
| + |
| + bool ready() const { |
| + AssertWatcherLockAcquired(); |
| + return last_known_result_ == MOJO_RESULT_OK || |
| + last_known_result_ == MOJO_RESULT_FAILED_PRECONDITION; |
| + } |
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<Watch>; |
| + |
| + ~Watch(); |
| + |
| +#if DCHECK_IS_ON() |
| + void AssertWatcherLockAcquired() const; |
| +#else |
| + void AssertWatcherLockAcquired() const {} |
| +#endif |
| + |
| + const scoped_refptr<WatcherDispatcher> watcher_; |
| + const scoped_refptr<Dispatcher> dispatcher_; |
| + const uintptr_t context_; |
| + const MojoHandleSignals signals_; |
| + |
| + // The result code with which this Watch would notify if currently armed, |
| + // based on the last known signaling state of |dispatcher_|. Guarded by the |
| + // owning WatcherDispatcher's lock. |
| + MojoResult last_known_result_ = MOJO_RESULT_UNKNOWN; |
| + |
| + // The last known signaling state of |dispatcher_|. Guarded by the owning |
| + // WatcherDispatcher's lock. |
| + MojoHandleSignalsState last_known_signals_state_ = {0, 0}; |
| + |
| + // Guards |is_cancelled_| below and mutually excludes individual watch |
| + // notification executions for this same watch context. |
| + // |
| + // Note that this should only be acquired from a RequestContext finalizer to |
| + // ensure that no other internal locks are already held. |
| + base::Lock notification_lock_; |
| + |
| + // Guarded by |notification_lock_|. |
| + bool is_cancelled_ = false; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Watch); |
| +}; |
| + |
| +} // namespace edk |
| +} // namespace mojo |
| + |
| +#endif // MOJO_EDK_SYSTEM_WATCH_H_ |