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

Side by Side Diff: mojo/public/cpp/system/simple_watcher.cc

Issue 2754863002: Mojo: Don't hold a watch context ref in SimpleWatcher posted task (Closed)
Patch Set: . 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
« no previous file with comments | « mojo/public/cpp/system/simple_watcher.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "mojo/public/cpp/system/simple_watcher.h" 5 #include "mojo/public/cpp/system/simple_watcher.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/macros.h" 8 #include "base/macros.h"
9 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/single_thread_task_runner.h" 10 #include "base/single_thread_task_runner.h"
11 #include "base/synchronization/lock.h" 11 #include "base/synchronization/lock.h"
12 #include "base/trace_event/heap_profiler.h" 12 #include "base/trace_event/heap_profiler.h"
13 #include "mojo/public/c/system/watcher.h" 13 #include "mojo/public/c/system/watcher.h"
14 14
15 namespace mojo { 15 namespace mojo {
16 16
17 // Thread-safe Context object used to dispatch watch notifications from a 17 // Thread-safe Context object used to dispatch watch notifications from a
18 // arbitrary threads. 18 // arbitrary threads.
19 class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> { 19 class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> {
20 public: 20 public:
21 // Creates a |Context| instance for a new watch on |watcher|, to watch 21 // Creates a |Context| instance for a new watch on |watcher|, to watch
22 // |handle| for |signals|. 22 // |handle| for |signals|.
23 static scoped_refptr<Context> Create( 23 static scoped_refptr<Context> Create(
24 base::WeakPtr<SimpleWatcher> watcher, 24 base::WeakPtr<SimpleWatcher> watcher,
25 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 25 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
26 WatcherHandle watcher_handle, 26 WatcherHandle watcher_handle,
27 Handle handle, 27 Handle handle,
28 MojoHandleSignals signals, 28 MojoHandleSignals signals,
29 int watch_id,
29 MojoResult* watch_result) { 30 MojoResult* watch_result) {
30 scoped_refptr<Context> context = new Context(watcher, task_runner); 31 scoped_refptr<Context> context =
32 new Context(watcher, task_runner, watch_id);
31 33
32 // If MojoWatch succeeds, it assumes ownership of a reference to |context|. 34 // If MojoWatch succeeds, it assumes ownership of a reference to |context|.
33 // In that case, this reference is balanced in CallNotify() when |result| is 35 // In that case, this reference is balanced in CallNotify() when |result| is
34 // |MOJO_RESULT_CANCELLED|. 36 // |MOJO_RESULT_CANCELLED|.
35 context->AddRef(); 37 context->AddRef();
36 38
37 *watch_result = MojoWatch(watcher_handle.value(), handle.value(), signals, 39 *watch_result = MojoWatch(watcher_handle.value(), handle.value(), signals,
38 context->value()); 40 context->value());
39 if (*watch_result != MOJO_RESULT_OK) { 41 if (*watch_result != MOJO_RESULT_OK) {
40 // Balanced by the AddRef() above since watching failed. 42 // Balanced by the AddRef() above since watching failed.
(...skipping 21 matching lines...) Expand all
62 64
63 void DisableCancellationNotifications() { 65 void DisableCancellationNotifications() {
64 base::AutoLock lock(lock_); 66 base::AutoLock lock(lock_);
65 enable_cancellation_notifications_ = false; 67 enable_cancellation_notifications_ = false;
66 } 68 }
67 69
68 private: 70 private:
69 friend class base::RefCountedThreadSafe<Context>; 71 friend class base::RefCountedThreadSafe<Context>;
70 72
71 Context(base::WeakPtr<SimpleWatcher> weak_watcher, 73 Context(base::WeakPtr<SimpleWatcher> weak_watcher,
72 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 74 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
73 : weak_watcher_(weak_watcher), task_runner_(task_runner) {} 75 int watch_id)
76 : weak_watcher_(weak_watcher),
77 task_runner_(task_runner),
78 watch_id_(watch_id) {}
74 ~Context() {} 79 ~Context() {}
75 80
76 void Notify(MojoResult result, 81 void Notify(MojoResult result,
77 MojoHandleSignalsState signals_state, 82 MojoHandleSignalsState signals_state,
78 MojoWatcherNotificationFlags flags) { 83 MojoWatcherNotificationFlags flags) {
79 if (result == MOJO_RESULT_CANCELLED) { 84 if (result == MOJO_RESULT_CANCELLED) {
80 // The SimpleWatcher may have explicitly cancelled this watch, so we don't 85 // The SimpleWatcher may have explicitly cancelled this watch, so we don't
81 // bother dispatching the notification - it would be ignored anyway. 86 // bother dispatching the notification - it would be ignored anyway.
82 // 87 //
83 // TODO(rockot): This shouldn't really be necessary, but there are already 88 // TODO(rockot): This shouldn't really be necessary, but there are already
84 // instances today where bindings object may be bound and subsequently 89 // instances today where bindings object may be bound and subsequently
85 // closed due to pipe error, all before the thread's TaskRunner has been 90 // closed due to pipe error, all before the thread's TaskRunner has been
86 // properly initialized. 91 // properly initialized.
87 base::AutoLock lock(lock_); 92 base::AutoLock lock(lock_);
88 if (!enable_cancellation_notifications_) 93 if (!enable_cancellation_notifications_)
89 return; 94 return;
90 } 95 }
91 96
92 if ((flags & MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM) && 97 if ((flags & MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM) &&
93 task_runner_->RunsTasksOnCurrentThread() && weak_watcher_ && 98 task_runner_->RunsTasksOnCurrentThread() && weak_watcher_ &&
94 weak_watcher_->is_default_task_runner_) { 99 weak_watcher_->is_default_task_runner_) {
95 // System notifications will trigger from the task runner passed to 100 // System notifications will trigger from the task runner passed to
96 // mojo::edk::InitIPCSupport(). In Chrome this happens to always be the 101 // mojo::edk::InitIPCSupport(). In Chrome this happens to always be the
97 // default task runner for the IO thread. 102 // default task runner for the IO thread.
98 weak_watcher_->OnHandleReady(make_scoped_refptr(this), result); 103 weak_watcher_->OnHandleReady(watch_id_, result);
99 } else { 104 } else {
100 task_runner_->PostTask( 105 task_runner_->PostTask(
101 FROM_HERE, base::Bind(&SimpleWatcher::OnHandleReady, weak_watcher_, 106 FROM_HERE, base::Bind(&SimpleWatcher::OnHandleReady, weak_watcher_,
102 make_scoped_refptr(this), result)); 107 watch_id_, result));
103 } 108 }
104 } 109 }
105 110
106 const base::WeakPtr<SimpleWatcher> weak_watcher_; 111 const base::WeakPtr<SimpleWatcher> weak_watcher_;
107 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 112 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
113 const int watch_id_;
108 114
109 base::Lock lock_; 115 base::Lock lock_;
110 bool enable_cancellation_notifications_ = true; 116 bool enable_cancellation_notifications_ = true;
111 117
112 DISALLOW_COPY_AND_ASSIGN(Context); 118 DISALLOW_COPY_AND_ASSIGN(Context);
113 }; 119 };
114 120
115 SimpleWatcher::SimpleWatcher(const tracked_objects::Location& from_here, 121 SimpleWatcher::SimpleWatcher(const tracked_objects::Location& from_here,
116 ArmingPolicy arming_policy, 122 ArmingPolicy arming_policy,
117 scoped_refptr<base::SingleThreadTaskRunner> runner) 123 scoped_refptr<base::SingleThreadTaskRunner> runner)
(...skipping 20 matching lines...) Expand all
138 144
139 MojoResult SimpleWatcher::Watch(Handle handle, 145 MojoResult SimpleWatcher::Watch(Handle handle,
140 MojoHandleSignals signals, 146 MojoHandleSignals signals,
141 const ReadyCallback& callback) { 147 const ReadyCallback& callback) {
142 DCHECK(thread_checker_.CalledOnValidThread()); 148 DCHECK(thread_checker_.CalledOnValidThread());
143 DCHECK(!IsWatching()); 149 DCHECK(!IsWatching());
144 DCHECK(!callback.is_null()); 150 DCHECK(!callback.is_null());
145 151
146 callback_ = callback; 152 callback_ = callback;
147 handle_ = handle; 153 handle_ = handle;
154 watch_id_ += 1;
148 155
149 MojoResult watch_result = MOJO_RESULT_UNKNOWN; 156 MojoResult watch_result = MOJO_RESULT_UNKNOWN;
150 context_ = 157 context_ = Context::Create(weak_factory_.GetWeakPtr(), task_runner_,
151 Context::Create(weak_factory_.GetWeakPtr(), task_runner_, 158 watcher_handle_.get(), handle_, signals, watch_id_,
152 watcher_handle_.get(), handle_, signals, &watch_result); 159 &watch_result);
153 if (!context_) { 160 if (!context_) {
154 handle_.set_value(kInvalidHandleValue); 161 handle_.set_value(kInvalidHandleValue);
155 callback_.Reset(); 162 callback_.Reset();
156 DCHECK_EQ(MOJO_RESULT_INVALID_ARGUMENT, watch_result); 163 DCHECK_EQ(MOJO_RESULT_INVALID_ARGUMENT, watch_result);
157 return watch_result; 164 return watch_result;
158 } 165 }
159 166
160 if (arming_policy_ == ArmingPolicy::AUTOMATIC) 167 if (arming_policy_ == ArmingPolicy::AUTOMATIC)
161 ArmOrNotify(); 168 ArmOrNotify();
162 169
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 return; 227 return;
221 228
222 MojoResult ready_result; 229 MojoResult ready_result;
223 MojoResult rv = Arm(&ready_result); 230 MojoResult rv = Arm(&ready_result);
224 if (rv == MOJO_RESULT_OK) 231 if (rv == MOJO_RESULT_OK)
225 return; 232 return;
226 233
227 DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv); 234 DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv);
228 task_runner_->PostTask(FROM_HERE, base::Bind(&SimpleWatcher::OnHandleReady, 235 task_runner_->PostTask(FROM_HERE, base::Bind(&SimpleWatcher::OnHandleReady,
229 weak_factory_.GetWeakPtr(), 236 weak_factory_.GetWeakPtr(),
230 context_, ready_result)); 237 watch_id_, ready_result));
231 } 238 }
232 239
233 void SimpleWatcher::OnHandleReady(scoped_refptr<const Context> context, 240 void SimpleWatcher::OnHandleReady(int watch_id, MojoResult result) {
234 MojoResult result) {
235 DCHECK(thread_checker_.CalledOnValidThread()); 241 DCHECK(thread_checker_.CalledOnValidThread());
236 242
237 // This notification may be for a previously watched context, in which case 243 // This notification may be for a previously watched context, in which case
238 // we just ignore it. 244 // we just ignore it.
239 if (context != context_) 245 if (watch_id != watch_id_)
240 return; 246 return;
241 247
242 ReadyCallback callback = callback_; 248 ReadyCallback callback = callback_;
243 if (result == MOJO_RESULT_CANCELLED) { 249 if (result == MOJO_RESULT_CANCELLED) {
244 // Implicit cancellation due to someone closing the watched handle. We clear 250 // Implicit cancellation due to someone closing the watched handle. We clear
245 // the SimppleWatcher's state before dispatching this. 251 // the SimppleWatcher's state before dispatching this.
246 context_ = nullptr; 252 context_ = nullptr;
247 handle_.set_value(kInvalidHandleValue); 253 handle_.set_value(kInvalidHandleValue);
248 callback_.Reset(); 254 callback_.Reset();
249 } 255 }
(...skipping 14 matching lines...) Expand all
264 // at most once in AUTOMATIC arming mode. 270 // at most once in AUTOMATIC arming mode.
265 if (result == MOJO_RESULT_FAILED_PRECONDITION) 271 if (result == MOJO_RESULT_FAILED_PRECONDITION)
266 unsatisfiable_ = true; 272 unsatisfiable_ = true;
267 273
268 if (arming_policy_ == ArmingPolicy::AUTOMATIC && IsWatching()) 274 if (arming_policy_ == ArmingPolicy::AUTOMATIC && IsWatching())
269 ArmOrNotify(); 275 ArmOrNotify();
270 } 276 }
271 } 277 }
272 278
273 } // namespace mojo 279 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/public/cpp/system/simple_watcher.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698