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 |