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

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

Issue 8653006: Remove custom Task implementations in base. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/location.h" 8 #include "base/location.h"
8 #include "base/message_loop.h" 9 #include "base/message_loop.h"
9 #include "base/synchronization/lock.h" 10 #include "base/synchronization/lock.h"
10 #include "base/synchronization/waitable_event.h" 11 #include "base/synchronization/waitable_event.h"
11 12
12 namespace base { 13 namespace base {
13 14
14 // ----------------------------------------------------------------------------- 15 // -----------------------------------------------------------------------------
15 // WaitableEventWatcher (async waits). 16 // WaitableEventWatcher (async waits).
16 // 17 //
(...skipping 28 matching lines...) Expand all
45 mutable Lock lock_; 46 mutable Lock lock_;
46 bool flag_; 47 bool flag_;
47 }; 48 };
48 49
49 // ----------------------------------------------------------------------------- 50 // -----------------------------------------------------------------------------
50 // This is an asynchronous waiter which posts a task to a MessageLoop when 51 // This is an asynchronous waiter which posts a task to a MessageLoop when
51 // fired. An AsyncWaiter may only be in a single wait-list. 52 // fired. An AsyncWaiter may only be in a single wait-list.
52 // ----------------------------------------------------------------------------- 53 // -----------------------------------------------------------------------------
53 class AsyncWaiter : public WaitableEvent::Waiter { 54 class AsyncWaiter : public WaitableEvent::Waiter {
54 public: 55 public:
55 AsyncWaiter(MessageLoop* message_loop, Task* task, Flag* flag) 56 AsyncWaiter(MessageLoop* message_loop,
57 const base::Closure& callback,
58 Flag* flag)
56 : message_loop_(message_loop), 59 : message_loop_(message_loop),
57 cb_task_(task), 60 callback_(callback),
58 flag_(flag) { } 61 flag_(flag) { }
59 62
60 bool Fire(WaitableEvent* event) { 63 bool Fire(WaitableEvent* event) {
61 if (flag_->value()) { 64 // Post the callback if we haven't been cancelled.
62 // If the callback has been canceled, we don't enqueue the task, we just 65 if (!flag_->value()) {
63 // delete it instead. 66 message_loop_->PostTask(FROM_HERE, callback_);
64 delete cb_task_;
65 } else {
66 message_loop_->PostTask(FROM_HERE, cb_task_);
67 } 67 }
68 68
69 // We are removed from the wait-list by the WaitableEvent itself. It only 69 // We are removed from the wait-list by the WaitableEvent itself. It only
70 // remains to delete ourselves. 70 // remains to delete ourselves.
71 delete this; 71 delete this;
72 72
73 // We can always return true because an AsyncWaiter is never in two 73 // We can always return true because an AsyncWaiter is never in two
74 // different wait-lists at the same time. 74 // different wait-lists at the same time.
75 return true; 75 return true;
76 } 76 }
77 77
78 // See StopWatching for discussion 78 // See StopWatching for discussion
79 bool Compare(void* tag) { 79 bool Compare(void* tag) {
80 return tag == flag_.get(); 80 return tag == flag_.get();
81 } 81 }
82 82
83 private: 83 private:
84 MessageLoop *const message_loop_; 84 MessageLoop *const message_loop_;
85 Task *const cb_task_; 85 base::Closure callback_;
86 scoped_refptr<Flag> flag_; 86 scoped_refptr<Flag> flag_;
87 }; 87 };
88 88
89 // ----------------------------------------------------------------------------- 89 // -----------------------------------------------------------------------------
90 // For async waits we need to make a callback in a MessageLoop thread. We do 90 // For async waits we need to make a callback in a MessageLoop thread. We do
91 // this by posting this task, which calls the delegate and keeps track of when 91 // this by posting a callback, which calls the delegate and keeps track of when
92 // the event is canceled. 92 // the event is canceled.
93 // ----------------------------------------------------------------------------- 93 // -----------------------------------------------------------------------------
94 class AsyncCallbackTask : public Task { 94 void AsyncCallbackHelper(scoped_refptr<Flag> flag,
willchan no longer on Chromium 2011/11/23 18:15:46 Do Flag* instead of scoped_refptr<Flag>. The type
dcheng 2011/11/23 18:47:49 Done, I wasn't sure if base::Bind() would automati
95 public: 95 WaitableEventWatcher::Delegate* delegate,
96 AsyncCallbackTask(Flag* flag, WaitableEventWatcher::Delegate* delegate, 96 WaitableEvent* event) {
97 WaitableEvent* event) 97 // Runs in MessageLoop thread.
98 : flag_(flag), 98 if (!flag->value()) {
99 delegate_(delegate), 99 // This is to let the WaitableEventWatcher know that the event has occured
100 event_(event) { 100 // because it needs to be able to return NULL from GetWatchedObject
101 flag->Set();
102 delegate->OnWaitableEventSignaled(event);
101 } 103 }
102 104 }
103 void Run() {
104 // Runs in MessageLoop thread.
105 if (!flag_->value()) {
106 // This is to let the WaitableEventWatcher know that the event has occured
107 // because it needs to be able to return NULL from GetWatchedObject
108 flag_->Set();
109 delegate_->OnWaitableEventSignaled(event_);
110 }
111
112 // We are deleted by the MessageLoop
113 }
114
115 private:
116 scoped_refptr<Flag> flag_;
117 WaitableEventWatcher::Delegate *const delegate_;
118 WaitableEvent *const event_;
119 };
120 105
121 WaitableEventWatcher::WaitableEventWatcher() 106 WaitableEventWatcher::WaitableEventWatcher()
122 : message_loop_(NULL), 107 : message_loop_(NULL),
123 cancel_flag_(NULL), 108 cancel_flag_(NULL),
124 waiter_(NULL), 109 waiter_(NULL),
125 callback_task_(NULL),
126 event_(NULL), 110 event_(NULL),
127 delegate_(NULL) { 111 delegate_(NULL) {
128 } 112 }
129 113
130 WaitableEventWatcher::~WaitableEventWatcher() { 114 WaitableEventWatcher::~WaitableEventWatcher() {
131 StopWatching(); 115 StopWatching();
132 } 116 }
133 117
134 // ----------------------------------------------------------------------------- 118 // -----------------------------------------------------------------------------
135 // The Handle is how the user cancels a wait. After deleting the Handle we 119 // The Handle is how the user cancels a wait. After deleting the Handle we
136 // insure that the delegate cannot be called. 120 // insure that the delegate cannot be called.
137 // ----------------------------------------------------------------------------- 121 // -----------------------------------------------------------------------------
138 bool WaitableEventWatcher::StartWatching 122 bool WaitableEventWatcher::StartWatching
139 (WaitableEvent* event, WaitableEventWatcher::Delegate* delegate) { 123 (WaitableEvent* event, WaitableEventWatcher::Delegate* delegate) {
140 MessageLoop *const current_ml = MessageLoop::current(); 124 MessageLoop *const current_ml = MessageLoop::current();
141 DCHECK(current_ml) << "Cannot create WaitableEventWatcher without a " 125 DCHECK(current_ml) << "Cannot create WaitableEventWatcher without a "
142 "current MessageLoop"; 126 "current MessageLoop";
143 127
144 // A user may call StartWatching from within the callback function. In this 128 // A user may call StartWatching from within the callback function. In this
145 // case, we won't know that we have finished watching, expect that the Flag 129 // case, we won't know that we have finished watching, expect that the Flag
146 // will have been set in AsyncCallbackTask::Run() 130 // will have been set in AsyncCallbackHelper().
147 if (cancel_flag_.get() && cancel_flag_->value()) { 131 if (cancel_flag_.get() && cancel_flag_->value()) {
148 if (message_loop_) { 132 if (message_loop_) {
149 message_loop_->RemoveDestructionObserver(this); 133 message_loop_->RemoveDestructionObserver(this);
150 message_loop_ = NULL; 134 message_loop_ = NULL;
151 } 135 }
152 136
153 cancel_flag_ = NULL; 137 cancel_flag_ = NULL;
154 } 138 }
155 139
156 DCHECK(!cancel_flag_.get()) << "StartWatching called while still watching"; 140 DCHECK(!cancel_flag_.get()) << "StartWatching called while still watching";
157 141
158 cancel_flag_ = new Flag; 142 cancel_flag_ = new Flag;
159 callback_task_ = new AsyncCallbackTask(cancel_flag_, delegate, event); 143 callback_ = base::Bind(&AsyncCallbackHelper, cancel_flag_, delegate, event);
160 WaitableEvent::WaitableEventKernel* kernel = event->kernel_.get(); 144 WaitableEvent::WaitableEventKernel* kernel = event->kernel_.get();
161 145
162 AutoLock locked(kernel->lock_); 146 AutoLock locked(kernel->lock_);
163 147
164 delegate_ = delegate; 148 delegate_ = delegate;
165 event_ = event; 149 event_ = event;
166 150
167 if (kernel->signaled_) { 151 if (kernel->signaled_) {
168 if (!kernel->manual_reset_) 152 if (!kernel->manual_reset_)
169 kernel->signaled_ = false; 153 kernel->signaled_ = false;
170 154
171 // No hairpinning - we can't call the delegate directly here. We have to 155 // No hairpinning - we can't call the delegate directly here. We have to
172 // enqueue a task on the MessageLoop as normal. 156 // enqueue a task on the MessageLoop as normal.
173 current_ml->PostTask(FROM_HERE, callback_task_); 157 current_ml->PostTask(FROM_HERE, callback_);
174 return true; 158 return true;
175 } 159 }
176 160
177 message_loop_ = current_ml; 161 message_loop_ = current_ml;
178 current_ml->AddDestructionObserver(this); 162 current_ml->AddDestructionObserver(this);
179 163
180 kernel_ = kernel; 164 kernel_ = kernel;
181 waiter_ = new AsyncWaiter(current_ml, callback_task_, cancel_flag_); 165 waiter_ = new AsyncWaiter(current_ml, callback_, cancel_flag_);
182 event->Enqueue(waiter_); 166 event->Enqueue(waiter_);
183 167
184 return true; 168 return true;
185 } 169 }
186 170
187 void WaitableEventWatcher::StopWatching() { 171 void WaitableEventWatcher::StopWatching() {
188 delegate_ = NULL; 172 delegate_ = NULL;
189 173
190 if (message_loop_) { 174 if (message_loop_) {
191 message_loop_->RemoveDestructionObserver(this); 175 message_loop_->RemoveDestructionObserver(this);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 // a tag which is good for the lifetime of this handle: the Flag. Since we 215 // a tag which is good for the lifetime of this handle: the Flag. Since we
232 // have a reference to the Flag, its memory cannot be reused while this object 216 // have a reference to the Flag, its memory cannot be reused while this object
233 // still exists. So if we find a waiter with the correct pointer value, and 217 // still exists. So if we find a waiter with the correct pointer value, and
234 // which shares a Flag pointer, we have a real match. 218 // which shares a Flag pointer, we have a real match.
235 if (kernel_->Dequeue(waiter_, cancel_flag_.get())) { 219 if (kernel_->Dequeue(waiter_, cancel_flag_.get())) {
236 // Case 2: the waiter hasn't been signaled yet; it was still on the wait 220 // Case 2: the waiter hasn't been signaled yet; it was still on the wait
237 // list. We've removed it, thus we can delete it and the task (which cannot 221 // list. We've removed it, thus we can delete it and the task (which cannot
238 // have been enqueued with the MessageLoop because the waiter was never 222 // have been enqueued with the MessageLoop because the waiter was never
239 // signaled) 223 // signaled)
240 delete waiter_; 224 delete waiter_;
241 delete callback_task_; 225 callback_.Reset();
242 cancel_flag_ = NULL; 226 cancel_flag_ = NULL;
243 return; 227 return;
244 } 228 }
245 229
246 // Case 3: the waiter isn't on the wait-list, thus it was signaled. It may 230 // Case 3: the waiter isn't on the wait-list, thus it was signaled. It may
247 // not have run yet, so we set the flag to tell it not to bother enqueuing the 231 // not have run yet, so we set the flag to tell it not to bother enqueuing the
248 // task on the MessageLoop, but to delete it instead. The Waiter deletes 232 // task on the MessageLoop, but to delete it instead. The Waiter deletes
249 // itself once run. 233 // itself once run.
250 cancel_flag_->Set(); 234 cancel_flag_->Set();
251 cancel_flag_ = NULL; 235 cancel_flag_ = NULL;
(...skipping 20 matching lines...) Expand all
272 // ----------------------------------------------------------------------------- 256 // -----------------------------------------------------------------------------
273 // This is called when the MessageLoop which the callback will be run it is 257 // This is called when the MessageLoop which the callback will be run it is
274 // deleted. We need to cancel the callback as if we had been deleted, but we 258 // deleted. We need to cancel the callback as if we had been deleted, but we
275 // will still be deleted at some point in the future. 259 // will still be deleted at some point in the future.
276 // ----------------------------------------------------------------------------- 260 // -----------------------------------------------------------------------------
277 void WaitableEventWatcher::WillDestroyCurrentMessageLoop() { 261 void WaitableEventWatcher::WillDestroyCurrentMessageLoop() {
278 StopWatching(); 262 StopWatching();
279 } 263 }
280 264
281 } // namespace base 265 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698