OLD | NEW |
---|---|
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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/message_pump_libevent.h" | 5 #include "base/message_pump_libevent.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 | 9 |
10 #include "eintr_wrapper.h" | 10 #include "eintr_wrapper.h" |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 Watcher* watcher = static_cast<Watcher*>(context); | 208 Watcher* watcher = static_cast<Watcher*>(context); |
209 | 209 |
210 if (flags & EV_WRITE) { | 210 if (flags & EV_WRITE) { |
211 watcher->OnFileCanWriteWithoutBlocking(fd); | 211 watcher->OnFileCanWriteWithoutBlocking(fd); |
212 } | 212 } |
213 if (flags & EV_READ) { | 213 if (flags & EV_READ) { |
214 watcher->OnFileCanReadWithoutBlocking(fd); | 214 watcher->OnFileCanReadWithoutBlocking(fd); |
215 } | 215 } |
216 } | 216 } |
217 | 217 |
218 // Tell libevent to break out of inner loop. | |
jeremy
2009/11/05 22:51:37
nit: expand the comment to point at the bug.
| |
219 static void timer_callback(int fd, short events, void *context) | |
220 { | |
221 event_base_loopbreak((struct event_base *)context); | |
222 } | |
223 | |
218 // Reentrant! | 224 // Reentrant! |
219 void MessagePumpLibevent::Run(Delegate* delegate) { | 225 void MessagePumpLibevent::Run(Delegate* delegate) { |
220 DCHECK(keep_running_) << "Quit must have been called outside of Run!"; | 226 DCHECK(keep_running_) << "Quit must have been called outside of Run!"; |
221 | 227 |
222 bool old_in_run = in_run_; | 228 bool old_in_run = in_run_; |
223 in_run_ = true; | 229 in_run_ = true; |
224 | 230 |
231 scoped_ptr<event> timer_event(new event); | |
232 | |
225 for (;;) { | 233 for (;;) { |
226 ScopedNSAutoreleasePool autorelease_pool; | 234 ScopedNSAutoreleasePool autorelease_pool; |
227 | 235 |
228 bool did_work = delegate->DoWork(); | 236 bool did_work = delegate->DoWork(); |
229 if (!keep_running_) | 237 if (!keep_running_) |
230 break; | 238 break; |
231 | 239 |
232 did_work |= delegate->DoDelayedWork(&delayed_work_time_); | 240 did_work |= delegate->DoDelayedWork(&delayed_work_time_); |
233 if (!keep_running_) | 241 if (!keep_running_) |
234 break; | 242 break; |
(...skipping 11 matching lines...) Expand all Loading... | |
246 // EVLOOP_ONCE tells libevent to only block once, | 254 // EVLOOP_ONCE tells libevent to only block once, |
247 // but to service all pending events when it wakes up. | 255 // but to service all pending events when it wakes up. |
248 if (delayed_work_time_.is_null()) { | 256 if (delayed_work_time_.is_null()) { |
249 event_base_loop(event_base_, EVLOOP_ONCE); | 257 event_base_loop(event_base_, EVLOOP_ONCE); |
250 } else { | 258 } else { |
251 TimeDelta delay = delayed_work_time_ - Time::Now(); | 259 TimeDelta delay = delayed_work_time_ - Time::Now(); |
252 if (delay > TimeDelta()) { | 260 if (delay > TimeDelta()) { |
253 struct timeval poll_tv; | 261 struct timeval poll_tv; |
254 poll_tv.tv_sec = delay.InSeconds(); | 262 poll_tv.tv_sec = delay.InSeconds(); |
255 poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond; | 263 poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond; |
256 event_base_loopexit(event_base_, &poll_tv); | 264 event_set(timer_event.get(), -1, 0, timer_callback, event_base_); |
265 event_base_set(event_base_, timer_event.get()); | |
266 event_add(timer_event.get(), &poll_tv); | |
257 event_base_loop(event_base_, EVLOOP_ONCE); | 267 event_base_loop(event_base_, EVLOOP_ONCE); |
268 event_del(timer_event.get()); | |
258 } else { | 269 } else { |
259 // It looks like delayed_work_time_ indicates a time in the past, so we | 270 // It looks like delayed_work_time_ indicates a time in the past, so we |
260 // need to call DoDelayedWork now. | 271 // need to call DoDelayedWork now. |
261 delayed_work_time_ = Time(); | 272 delayed_work_time_ = Time(); |
262 } | 273 } |
263 } | 274 } |
264 } | 275 } |
265 | 276 |
266 keep_running_ = true; | 277 keep_running_ = true; |
267 in_run_ = old_in_run; | 278 in_run_ = old_in_run; |
(...skipping 15 matching lines...) Expand all Loading... | |
283 } | 294 } |
284 | 295 |
285 void MessagePumpLibevent::ScheduleDelayedWork(const Time& delayed_work_time) { | 296 void MessagePumpLibevent::ScheduleDelayedWork(const Time& delayed_work_time) { |
286 // We know that we can't be blocked on Wait right now since this method can | 297 // We know that we can't be blocked on Wait right now since this method can |
287 // only be called on the same thread as Run, so we only need to update our | 298 // only be called on the same thread as Run, so we only need to update our |
288 // record of how long to sleep when we do sleep. | 299 // record of how long to sleep when we do sleep. |
289 delayed_work_time_ = delayed_work_time; | 300 delayed_work_time_ = delayed_work_time; |
290 } | 301 } |
291 | 302 |
292 } // namespace base | 303 } // namespace base |
OLD | NEW |