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

Side by Side Diff: ipc/mojo/async_handle_waiter.cc

Issue 973213002: Make AsyncHandleWaiter reenterancy-safe (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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 | « no previous file | 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "ipc/mojo/async_handle_waiter.h" 5 #include "ipc/mojo/async_handle_waiter.h"
6 6
7 #include "base/atomic_ref_count.h" 7 #include "base/atomic_ref_count.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/bind_helpers.h" 9 #include "base/bind_helpers.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 14 matching lines...) Expand all
25 // |HandleIsReady()| and the bound |this| have to be thread-safe. 25 // |HandleIsReady()| and the bound |this| have to be thread-safe.
26 class AsyncHandleWaiter::Context 26 class AsyncHandleWaiter::Context
27 : public base::RefCountedThreadSafe<AsyncHandleWaiter::Context, 27 : public base::RefCountedThreadSafe<AsyncHandleWaiter::Context,
28 AsyncHandleWaiterContextTraits>, 28 AsyncHandleWaiterContextTraits>,
29 public base::MessageLoopForIO::IOObserver { 29 public base::MessageLoopForIO::IOObserver {
30 public: 30 public:
31 Context(base::WeakPtr<AsyncHandleWaiter> waiter) 31 Context(base::WeakPtr<AsyncHandleWaiter> waiter)
32 : io_runner_(base::MessageLoopForIO::current()->task_runner()), 32 : io_runner_(base::MessageLoopForIO::current()->task_runner()),
33 waiter_(waiter), 33 waiter_(waiter),
34 last_result_(MOJO_RESULT_INTERNAL), 34 last_result_(MOJO_RESULT_INTERNAL),
35 processing_(false), 35 processing_(0),
36 should_invoke_callback_(false) { 36 should_invoke_callback_(false) {
37 base::MessageLoopForIO::current()->AddIOObserver(this); 37 base::MessageLoopForIO::current()->AddIOObserver(this);
38 } 38 }
39 39
40 void HandleIsReady(MojoResult result) { 40 void HandleIsReady(MojoResult result) {
41 last_result_ = result; 41 last_result_ = result;
42 42
43 // If the signaling happens in the IO handler, use |IOObserver| callback 43 // If the signaling happens in the IO handler, use |IOObserver| callback
44 // to invoke the callback. 44 // to invoke the callback.
45 if (IsCalledFromIOHandler()) { 45 if (IsCalledFromIOHandler()) {
(...skipping 14 matching lines...) Expand all
60 DCHECK(base::MessageLoopForIO::current()->task_runner() == io_runner_); 60 DCHECK(base::MessageLoopForIO::current()->task_runner() == io_runner_);
61 base::MessageLoopForIO::current()->RemoveIOObserver(this); 61 base::MessageLoopForIO::current()->RemoveIOObserver(this);
62 } 62 }
63 63
64 bool IsCalledFromIOHandler() const { 64 bool IsCalledFromIOHandler() const {
65 base::MessageLoop* loop = base::MessageLoop::current(); 65 base::MessageLoop* loop = base::MessageLoop::current();
66 if (!loop) 66 if (!loop)
67 return false; 67 return false;
68 if (loop->task_runner() != io_runner_) 68 if (loop->task_runner() != io_runner_)
69 return false; 69 return false;
70 return processing_; 70 return 0 < processing_;
viettrungluu 2015/03/03 22:03:33 nit: "processing_ > 0" would probably be more read
71 } 71 }
72 72
73 // Called from |io_runner_| thus safe to touch |waiter_|. 73 // Called from |io_runner_| thus safe to touch |waiter_|.
74 void InvokeWaiterCallback() { 74 void InvokeWaiterCallback() {
75 MojoResult result = last_result_; 75 MojoResult result = last_result_;
76 last_result_ = MOJO_RESULT_INTERNAL; 76 last_result_ = MOJO_RESULT_INTERNAL;
77 if (waiter_) 77 if (waiter_)
78 waiter_->InvokeCallback(result); 78 waiter_->InvokeCallback(result);
79 } 79 }
80 80
81 // IOObserver implementation: 81 // IOObserver implementation:
82 82
83 void WillProcessIOEvent() override { 83 void WillProcessIOEvent() override {
84 DCHECK(!should_invoke_callback_); 84 DCHECK(!should_invoke_callback_);
85 DCHECK(!processing_); 85 DCHECK_GE(processing_, 0);
86 processing_ = true; 86 processing_++;
87 } 87 }
88 88
89 void DidProcessIOEvent() override { 89 void DidProcessIOEvent() override {
90 DCHECK(processing_); 90 DCHECK_GE(processing_, 1);
91
92 // Leaving a nested loop.
93 if (1 < processing_) {
viettrungluu 2015/03/03 22:03:33 processing_ > 1
Hajime Morrita 2015/03/04 23:16:08 Done.
94 processing_--;
95 return;
viettrungluu 2015/03/03 22:03:33 Why do we not want to do any of the stuff below in
Hajime Morrita 2015/03/04 23:16:08 It can cause nested IO callback, which isn't what
96 }
91 97
92 // The zero |waiter_| indicates that |this| have lost the owner and can be 98 // The zero |waiter_| indicates that |this| have lost the owner and can be
93 // under destruction. So we cannot wrap it with a |scoped_refptr| anymore. 99 // under destruction. So we cannot wrap it with a |scoped_refptr| anymore.
94 if (!waiter_) { 100 if (!waiter_) {
95 should_invoke_callback_ = false; 101 should_invoke_callback_ = false;
96 processing_ = false; 102 processing_--;
97 return; 103 return;
98 } 104 }
99 105
100 // We have to protect |this| because |AsyncHandleWaiter| can be 106 // We have to protect |this| because |AsyncHandleWaiter| can be
101 // deleted during the callback. 107 // deleted during the callback.
102 scoped_refptr<Context> protect(this); 108 scoped_refptr<Context> protect(this);
103 while (should_invoke_callback_) { 109 while (should_invoke_callback_) {
104 should_invoke_callback_ = false; 110 should_invoke_callback_ = false;
105 InvokeWaiterCallback(); 111 InvokeWaiterCallback();
106 } 112 }
107 113
108 processing_ = false; 114 processing_--;
109 } 115 }
110 116
111 // Only |io_runner_| is accessed from arbitrary threads. Others are touched 117 // Only |io_runner_| is accessed from arbitrary threads. Others are touched
112 // only from the IO thread. 118 // only from the IO thread.
113 const scoped_refptr<base::TaskRunner> io_runner_; 119 const scoped_refptr<base::TaskRunner> io_runner_;
114 120
115 const base::WeakPtr<AsyncHandleWaiter> waiter_; 121 const base::WeakPtr<AsyncHandleWaiter> waiter_;
116 MojoResult last_result_; 122 MojoResult last_result_;
117 bool processing_; 123 int processing_;
viettrungluu 2015/03/03 22:03:33 nit: Maybe rename this to something slightly more
Hajime Morrita 2015/03/04 23:16:08 Done.
118 bool should_invoke_callback_; 124 bool should_invoke_callback_;
119 125
120 DISALLOW_COPY_AND_ASSIGN(Context); 126 DISALLOW_COPY_AND_ASSIGN(Context);
121 }; 127 };
122 128
123 AsyncHandleWaiter::AsyncHandleWaiter(base::Callback<void(MojoResult)> callback) 129 AsyncHandleWaiter::AsyncHandleWaiter(base::Callback<void(MojoResult)> callback)
124 : callback_(callback), 130 : callback_(callback),
125 weak_factory_(this) { 131 weak_factory_(this) {
126 context_ = new Context(weak_factory_.GetWeakPtr()); 132 context_ = new Context(weak_factory_.GetWeakPtr());
127 } 133 }
(...skipping 15 matching lines...) Expand all
143 void AsyncHandleWaiterContextTraits::Destruct( 149 void AsyncHandleWaiterContextTraits::Destruct(
144 const AsyncHandleWaiter::Context* context) { 150 const AsyncHandleWaiter::Context* context) {
145 context->io_runner_->PostTask( 151 context->io_runner_->PostTask(
146 FROM_HERE, 152 FROM_HERE,
147 base::Bind(&base::DeletePointer<const AsyncHandleWaiter::Context>, 153 base::Bind(&base::DeletePointer<const AsyncHandleWaiter::Context>,
148 base::Unretained(context))); 154 base::Unretained(context)));
149 } 155 }
150 156
151 } // namespace internal 157 } // namespace internal
152 } // namespace IPC 158 } // namespace IPC
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698