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

Side by Side Diff: base/synchronization/waitable_event_watcher_posix.cc

Issue 12094106: Refactor: Simplify WaitableEventWatcher. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 10 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "base/synchronization/waitable_event_watcher.h" 5 #include "base/synchronization/waitable_event_watcher.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/synchronization/lock.h" 10 #include "base/synchronization/lock.h"
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 base::Closure callback_; 90 base::Closure callback_;
91 scoped_refptr<Flag> flag_; 91 scoped_refptr<Flag> flag_;
92 }; 92 };
93 93
94 // ----------------------------------------------------------------------------- 94 // -----------------------------------------------------------------------------
95 // For async waits we need to make a callback in a MessageLoop thread. We do 95 // For async waits we need to make a callback in a MessageLoop thread. We do
96 // this by posting a callback, which calls the delegate and keeps track of when 96 // this by posting a callback, which calls the delegate and keeps track of when
97 // the event is canceled. 97 // the event is canceled.
98 // ----------------------------------------------------------------------------- 98 // -----------------------------------------------------------------------------
99 void AsyncCallbackHelper(Flag* flag, 99 void AsyncCallbackHelper(Flag* flag,
100 WaitableEventWatcher::Delegate* delegate, 100 const WaitableEventWatcher::EventCallback& callback,
101 WaitableEvent* event) { 101 WaitableEvent* event) {
102 // Runs in MessageLoop thread. 102 // Runs in MessageLoop thread.
103 if (!flag->value()) { 103 if (!flag->value()) {
104 // This is to let the WaitableEventWatcher know that the event has occured 104 // This is to let the WaitableEventWatcher know that the event has occured
105 // because it needs to be able to return NULL from GetWatchedObject 105 // because it needs to be able to return NULL from GetWatchedObject
106 flag->Set(); 106 flag->Set();
107 delegate->OnWaitableEventSignaled(event); 107 callback.Run(event);
108 } 108 }
109 } 109 }
110 110
111 WaitableEventWatcher::WaitableEventWatcher() 111 WaitableEventWatcher::WaitableEventWatcher()
112 : message_loop_(NULL), 112 : message_loop_(NULL),
113 cancel_flag_(NULL), 113 cancel_flag_(NULL),
114 waiter_(NULL), 114 waiter_(NULL),
115 event_(NULL), 115 event_(NULL) {
116 delegate_(NULL) {
117 } 116 }
118 117
119 WaitableEventWatcher::~WaitableEventWatcher() { 118 WaitableEventWatcher::~WaitableEventWatcher() {
120 StopWatching(); 119 StopWatching();
121 } 120 }
122 121
123 // ----------------------------------------------------------------------------- 122 // -----------------------------------------------------------------------------
124 // The Handle is how the user cancels a wait. After deleting the Handle we 123 // The Handle is how the user cancels a wait. After deleting the Handle we
125 // insure that the delegate cannot be called. 124 // insure that the delegate cannot be called.
126 // ----------------------------------------------------------------------------- 125 // -----------------------------------------------------------------------------
127 bool WaitableEventWatcher::StartWatching 126 bool WaitableEventWatcher::StartWatching(
128 (WaitableEvent* event, WaitableEventWatcher::Delegate* delegate) { 127 WaitableEvent* event,
128 const EventCallback& callback) {
129 MessageLoop *const current_ml = MessageLoop::current(); 129 MessageLoop *const current_ml = MessageLoop::current();
130 DCHECK(current_ml) << "Cannot create WaitableEventWatcher without a " 130 DCHECK(current_ml) << "Cannot create WaitableEventWatcher without a "
131 "current MessageLoop"; 131 "current MessageLoop";
132 132
133 // A user may call StartWatching from within the callback function. In this 133 // A user may call StartWatching from within the callback function. In this
134 // case, we won't know that we have finished watching, expect that the Flag 134 // case, we won't know that we have finished watching, expect that the Flag
135 // will have been set in AsyncCallbackHelper(). 135 // will have been set in AsyncCallbackHelper().
136 if (cancel_flag_.get() && cancel_flag_->value()) { 136 if (cancel_flag_.get() && cancel_flag_->value()) {
137 if (message_loop_) { 137 if (message_loop_) {
138 message_loop_->RemoveDestructionObserver(this); 138 message_loop_->RemoveDestructionObserver(this);
139 message_loop_ = NULL; 139 message_loop_ = NULL;
140 } 140 }
141 141
142 cancel_flag_ = NULL; 142 cancel_flag_ = NULL;
143 } 143 }
144 144
145 DCHECK(!cancel_flag_.get()) << "StartWatching called while still watching"; 145 DCHECK(!cancel_flag_.get()) << "StartWatching called while still watching";
146 146
147 cancel_flag_ = new Flag; 147 cancel_flag_ = new Flag;
148 callback_ = base::Bind(&AsyncCallbackHelper, cancel_flag_, delegate, event); 148 callback_ = callback;
149 internal_callback_ =
150 base::Bind(&AsyncCallbackHelper, cancel_flag_, callback_, event);
149 WaitableEvent::WaitableEventKernel* kernel = event->kernel_.get(); 151 WaitableEvent::WaitableEventKernel* kernel = event->kernel_.get();
150 152
151 AutoLock locked(kernel->lock_); 153 AutoLock locked(kernel->lock_);
152 154
153 delegate_ = delegate;
154 event_ = event; 155 event_ = event;
155 156
156 if (kernel->signaled_) { 157 if (kernel->signaled_) {
157 if (!kernel->manual_reset_) 158 if (!kernel->manual_reset_)
158 kernel->signaled_ = false; 159 kernel->signaled_ = false;
159 160
160 // No hairpinning - we can't call the delegate directly here. We have to 161 // No hairpinning - we can't call the delegate directly here. We have to
161 // enqueue a task on the MessageLoop as normal. 162 // enqueue a task on the MessageLoop as normal.
162 current_ml->PostTask(FROM_HERE, callback_); 163 current_ml->PostTask(FROM_HERE, internal_callback_);
163 return true; 164 return true;
164 } 165 }
165 166
166 message_loop_ = current_ml; 167 message_loop_ = current_ml;
167 current_ml->AddDestructionObserver(this); 168 current_ml->AddDestructionObserver(this);
168 169
169 kernel_ = kernel; 170 kernel_ = kernel;
170 waiter_ = new AsyncWaiter(current_ml, callback_, cancel_flag_); 171 waiter_ = new AsyncWaiter(current_ml, internal_callback_, cancel_flag_);
171 event->Enqueue(waiter_); 172 event->Enqueue(waiter_);
172 173
173 return true; 174 return true;
174 } 175 }
175 176
176 void WaitableEventWatcher::StopWatching() { 177 void WaitableEventWatcher::StopWatching() {
177 delegate_ = NULL; 178 callback_.Reset();
178 179
179 if (message_loop_) { 180 if (message_loop_) {
180 message_loop_->RemoveDestructionObserver(this); 181 message_loop_->RemoveDestructionObserver(this);
181 message_loop_ = NULL; 182 message_loop_ = NULL;
182 } 183 }
183 184
184 if (!cancel_flag_.get()) // if not currently watching... 185 if (!cancel_flag_.get()) // if not currently watching...
185 return; 186 return;
186 187
187 if (cancel_flag_->value()) { 188 if (cancel_flag_->value()) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 // a tag which is good for the lifetime of this handle: the Flag. Since we 221 // a tag which is good for the lifetime of this handle: the Flag. Since we
221 // have a reference to the Flag, its memory cannot be reused while this object 222 // have a reference to the Flag, its memory cannot be reused while this object
222 // still exists. So if we find a waiter with the correct pointer value, and 223 // still exists. So if we find a waiter with the correct pointer value, and
223 // which shares a Flag pointer, we have a real match. 224 // which shares a Flag pointer, we have a real match.
224 if (kernel_->Dequeue(waiter_, cancel_flag_.get())) { 225 if (kernel_->Dequeue(waiter_, cancel_flag_.get())) {
225 // Case 2: the waiter hasn't been signaled yet; it was still on the wait 226 // Case 2: the waiter hasn't been signaled yet; it was still on the wait
226 // list. We've removed it, thus we can delete it and the task (which cannot 227 // list. We've removed it, thus we can delete it and the task (which cannot
227 // have been enqueued with the MessageLoop because the waiter was never 228 // have been enqueued with the MessageLoop because the waiter was never
228 // signaled) 229 // signaled)
229 delete waiter_; 230 delete waiter_;
230 callback_.Reset(); 231 internal_callback_.Reset();
231 cancel_flag_ = NULL; 232 cancel_flag_ = NULL;
232 return; 233 return;
233 } 234 }
234 235
235 // Case 3: the waiter isn't on the wait-list, thus it was signaled. It may 236 // Case 3: the waiter isn't on the wait-list, thus it was signaled. It may
236 // not have run yet, so we set the flag to tell it not to bother enqueuing the 237 // not have run yet, so we set the flag to tell it not to bother enqueuing the
237 // task on the MessageLoop, but to delete it instead. The Waiter deletes 238 // task on the MessageLoop, but to delete it instead. The Waiter deletes
238 // itself once run. 239 // itself once run.
239 cancel_flag_->Set(); 240 cancel_flag_->Set();
240 cancel_flag_ = NULL; 241 cancel_flag_ = NULL;
(...skipping 20 matching lines...) Expand all
261 // ----------------------------------------------------------------------------- 262 // -----------------------------------------------------------------------------
262 // This is called when the MessageLoop which the callback will be run it is 263 // This is called when the MessageLoop which the callback will be run it is
263 // deleted. We need to cancel the callback as if we had been deleted, but we 264 // deleted. We need to cancel the callback as if we had been deleted, but we
264 // will still be deleted at some point in the future. 265 // will still be deleted at some point in the future.
265 // ----------------------------------------------------------------------------- 266 // -----------------------------------------------------------------------------
266 void WaitableEventWatcher::WillDestroyCurrentMessageLoop() { 267 void WaitableEventWatcher::WillDestroyCurrentMessageLoop() {
267 StopWatching(); 268 StopWatching();
268 } 269 }
269 270
270 } // namespace base 271 } // namespace base
OLDNEW
« no previous file with comments | « base/synchronization/waitable_event_watcher.h ('k') | base/synchronization/waitable_event_watcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698