Chromium Code Reviews| 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 |