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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
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 #include "mojo/edk/system/watch.h"
6
7 #include "mojo/edk/system/request_context.h"
8 #include "mojo/edk/system/watcher_dispatcher.h"
9
10 namespace mojo {
11 namespace edk {
12
13 Watch::Watch(const scoped_refptr<WatcherDispatcher>& watcher,
14 const scoped_refptr<Dispatcher>& dispatcher,
15 uintptr_t context,
16 MojoHandleSignals signals)
17 : watcher_(watcher),
18 dispatcher_(dispatcher),
19 context_(context),
20 signals_(signals) {}
21
22 bool Watch::NotifyState(const HandleSignalsState& state,
23 bool allowed_to_call_callback) {
24 AssertWatcherLockAcquired();
25
26 // NOTE: This method must NEVER call into |dispatcher_| directly, because it
27 // may be called while |dispatcher_| holds a lock.
28
29 MojoResult rv = MOJO_RESULT_SHOULD_WAIT;
30 RequestContext* const request_context = RequestContext::current();
31 if (state.satisfies(signals_)) {
32 rv = MOJO_RESULT_OK;
33 if (allowed_to_call_callback && rv != last_known_result_) {
34 request_context->AddWatchNotifyFinalizer(this, MOJO_RESULT_OK, state);
35 }
36 } else if (!state.can_satisfy(signals_)) {
37 rv = MOJO_RESULT_FAILED_PRECONDITION;
38 if (allowed_to_call_callback && rv != last_known_result_) {
39 request_context->AddWatchNotifyFinalizer(
40 this, MOJO_RESULT_FAILED_PRECONDITION, state);
41 }
42 }
43
44 last_known_signals_state_ =
45 *static_cast<const MojoHandleSignalsState*>(&state);
46 last_known_result_ = rv;
47 return ready();
48 }
49
50 void Watch::Cancel() {
51 RequestContext::current()->AddWatchCancelFinalizer(this);
52 }
53
54 void Watch::InvokeCallback(MojoResult result,
55 const HandleSignalsState& state,
56 MojoWatcherNotificationFlags flags) {
57 // We hold the lock through invocation to ensure that only one notification
58 // callback runs for this context at any given time.
59 base::AutoLock lock(notification_lock_);
60 if (result == MOJO_RESULT_CANCELLED) {
61 // Make sure cancellation is the last notification we dispatch.
62 DCHECK(!is_cancelled_);
63 is_cancelled_ = true;
64 } else if (is_cancelled_) {
65 return;
66 }
67
68 // NOTE: This will acquire |watcher_|'s internal lock. It's safe because a
69 // thread can only enter InvokeCallback() from within a RequestContext
70 // destructor where no dispatcher locks are held.
71 watcher_->InvokeWatchCallback(context_, result, state, flags);
72 }
73
74 Watch::~Watch() {}
75
76 #if DCHECK_IS_ON()
77 void Watch::AssertWatcherLockAcquired() const {
78 watcher_->lock_.AssertAcquired();
79 }
80 #endif
81
82 } // namespace edk
83 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698