Index: mojo/edk/system/request_context.cc |
diff --git a/mojo/edk/system/request_context.cc b/mojo/edk/system/request_context.cc |
index 6370ab11c77f4464d4caf8226b4e6209867721e7..5de65d7b641521fa64ea00e57257c5ae12802fcc 100644 |
--- a/mojo/edk/system/request_context.cc |
+++ b/mojo/edk/system/request_context.cc |
@@ -36,27 +36,34 @@ RequestContext::~RequestContext() { |
// since we're starting over at the bottom of the stack. |
tls_context_->Set(nullptr); |
- MojoWatchNotificationFlags flags = MOJO_WATCH_NOTIFICATION_FLAG_NONE; |
+ MojoWatcherNotificationFlags flags = MOJO_WATCHER_NOTIFICATION_FLAG_NONE; |
if (source_ == Source::SYSTEM) |
- flags |= MOJO_WATCH_NOTIFICATION_FLAG_FROM_SYSTEM; |
+ flags |= MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM; |
- // We run all cancellation finalizers first. This is necessary because it's |
- // possible that one of the cancelled watchers has other pending finalizers |
+ // We send all cancellation notifications first. This is necessary because |
+ // it's possible that cancelled watches have other pending notifications |
// attached to this RequestContext. |
// |
- // From the application's perspective the watch has already been cancelled, |
- // so we have to honor our contract which guarantees no more notifications. |
- for (const scoped_refptr<Watcher>& watcher : |
- watch_cancel_finalizers_.container()) |
- watcher->Cancel(); |
+ // From the application's perspective the watch is cancelled as soon as this |
+ // notification is received, and dispatching the cancellation notification |
+ // updates some internal Watch state to ensure no further notifications |
+ // fire. Because notifications on a single Watch are mutually exclusive, |
+ // this is sufficient to guarantee that MOJO_RESULT_CANCELLED is the last |
+ // notification received; which is the guarantee the API makes. |
+ for (const scoped_refptr<Watch>& watch : |
+ watch_cancel_finalizers_.container()) { |
+ static const HandleSignalsState closed_state = {0, 0}; |
+ |
+ // Establish a new RequestContext to capture and run any new notifications |
+ // triggered by the callback invocation. |
+ RequestContext inner_context(source_); |
+ watch->InvokeCallback(MOJO_RESULT_CANCELLED, closed_state, flags); |
+ } |
for (const WatchNotifyFinalizer& watch : |
- watch_notify_finalizers_.container()) { |
- // Establish a new request context for the extent of each callback to |
- // ensure that they don't themselves invoke callbacks while holding a |
- // watcher lock. |
- RequestContext request_context(source_); |
- watch.watcher->MaybeInvokeCallback(watch.result, watch.state, flags); |
+ watch_notify_finalizers_.container()) { |
+ RequestContext inner_context(source_); |
+ watch.watch->InvokeCallback(watch.result, watch.state, flags); |
} |
} else { |
// It should be impossible for nested contexts to have finalizers. |
@@ -71,18 +78,17 @@ RequestContext* RequestContext::current() { |
return g_current_context.Pointer()->Get(); |
} |
-void RequestContext::AddWatchNotifyFinalizer( |
- scoped_refptr<Watcher> watcher, |
- MojoResult result, |
- const HandleSignalsState& state) { |
+void RequestContext::AddWatchNotifyFinalizer(scoped_refptr<Watch> watch, |
+ MojoResult result, |
+ const HandleSignalsState& state) { |
DCHECK(IsCurrent()); |
watch_notify_finalizers_->push_back( |
- WatchNotifyFinalizer(std::move(watcher), result, state)); |
+ WatchNotifyFinalizer(std::move(watch), result, state)); |
} |
-void RequestContext::AddWatchCancelFinalizer(scoped_refptr<Watcher> watcher) { |
+void RequestContext::AddWatchCancelFinalizer(scoped_refptr<Watch> watch) { |
DCHECK(IsCurrent()); |
- watch_cancel_finalizers_->push_back(std::move(watcher)); |
+ watch_cancel_finalizers_->push_back(std::move(watch)); |
} |
bool RequestContext::IsCurrent() const { |
@@ -90,10 +96,10 @@ bool RequestContext::IsCurrent() const { |
} |
RequestContext::WatchNotifyFinalizer::WatchNotifyFinalizer( |
- scoped_refptr<Watcher> watcher, |
+ scoped_refptr<Watch> watch, |
MojoResult result, |
const HandleSignalsState& state) |
- : watcher(std::move(watcher)), result(result), state(state) {} |
+ : watch(std::move(watch)), result(result), state(state) {} |
RequestContext::WatchNotifyFinalizer::WatchNotifyFinalizer( |
const WatchNotifyFinalizer& other) = default; |