Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(647)

Unified Diff: mojo/edk/system/watch.cc

Issue 2725133002: Mojo: Armed Watchers (Closed)
Patch Set: rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/edk/system/watch.cc
diff --git a/mojo/edk/system/watch.cc b/mojo/edk/system/watch.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cf08ac37ee5a0d5686fd64e0aaeee486c0c220ca
--- /dev/null
+++ b/mojo/edk/system/watch.cc
@@ -0,0 +1,83 @@
+// 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.
+
+#include "mojo/edk/system/watch.h"
+
+#include "mojo/edk/system/request_context.h"
+#include "mojo/edk/system/watcher_dispatcher.h"
+
+namespace mojo {
+namespace edk {
+
+Watch::Watch(const scoped_refptr<WatcherDispatcher>& watcher,
+ const scoped_refptr<Dispatcher>& dispatcher,
+ uintptr_t context,
+ MojoHandleSignals signals)
+ : watcher_(watcher),
+ dispatcher_(dispatcher),
+ context_(context),
+ signals_(signals) {}
+
+bool Watch::NotifyState(const HandleSignalsState& state,
+ bool allowed_to_call_callback) {
+ AssertWatcherLockAcquired();
+
+ // NOTE: This method must NEVER call into |dispatcher_| directly, because it
+ // may be called while |dispatcher_| holds a lock.
+
+ MojoResult rv = MOJO_RESULT_SHOULD_WAIT;
+ RequestContext* const request_context = RequestContext::current();
+ if (state.satisfies(signals_)) {
+ rv = MOJO_RESULT_OK;
+ if (allowed_to_call_callback && rv != last_known_result_) {
+ request_context->AddWatchNotifyFinalizer(this, MOJO_RESULT_OK, state);
+ }
+ } else if (!state.can_satisfy(signals_)) {
+ rv = MOJO_RESULT_FAILED_PRECONDITION;
+ if (allowed_to_call_callback && rv != last_known_result_) {
+ request_context->AddWatchNotifyFinalizer(
+ this, MOJO_RESULT_FAILED_PRECONDITION, state);
+ }
+ }
+
+ last_known_signals_state_ =
+ *static_cast<const MojoHandleSignalsState*>(&state);
+ last_known_result_ = rv;
+ return ready();
+}
+
+void Watch::Cancel() {
+ RequestContext::current()->AddWatchCancelFinalizer(this);
+}
+
+void Watch::InvokeCallback(MojoResult result,
+ const HandleSignalsState& state,
+ MojoWatcherNotificationFlags flags) {
+ // We hold the lock through invocation to ensure that only one notification
+ // callback runs for this context at any given time.
+ base::AutoLock lock(notification_lock_);
+ if (result == MOJO_RESULT_CANCELLED) {
+ // Make sure cancellation is the last notification we dispatch.
+ DCHECK(!is_cancelled_);
+ is_cancelled_ = true;
+ } else if (is_cancelled_) {
+ return;
+ }
+
+ // NOTE: This will acquire |watcher_|'s internal lock. It's safe because a
+ // thread can only enter InvokeCallback() from within a RequestContext
+ // destructor where no dispatcher locks are held.
+ watcher_->InvokeWatchCallback(context_, result, state, flags);
+}
+
+Watch::~Watch() {}
+
+#if DCHECK_IS_ON()
+void Watch::AssertWatcherLockAcquired() const {
+ watcher_->lock_.AssertAcquired();
+}
+#endif
+
+} // namespace edk
+} // namespace mojo

Powered by Google App Engine
This is Rietveld 408576698