Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |