| OLD | NEW |
| 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/message_loop/message_pump_libevent.h" | 5 #include "base/message_loop/message_pump_libevent.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <unistd.h> | 9 #include <unistd.h> |
| 10 | 10 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 watcher_->OnFileCanWriteWithoutBlocking(fd); | 112 watcher_->OnFileCanWriteWithoutBlocking(fd); |
| 113 pump->DidProcessIOEvent(); | 113 pump->DidProcessIOEvent(); |
| 114 } | 114 } |
| 115 | 115 |
| 116 MessagePumpLibevent::MessagePumpLibevent() | 116 MessagePumpLibevent::MessagePumpLibevent() |
| 117 : keep_running_(true), | 117 : keep_running_(true), |
| 118 in_run_(false), | 118 in_run_(false), |
| 119 processed_io_events_(false), | 119 processed_io_events_(false), |
| 120 event_base_(event_base_new()), | 120 event_base_(event_base_new()), |
| 121 wakeup_pipe_in_(-1), | 121 wakeup_pipe_in_(-1), |
| 122 wakeup_pipe_out_(-1) { | 122 wakeup_pipe_out_(-1), |
| 123 event_source_(nullptr) { |
| 123 if (!Init()) | 124 if (!Init()) |
| 124 NOTREACHED(); | 125 NOTREACHED(); |
| 125 } | 126 } |
| 126 | 127 |
| 127 MessagePumpLibevent::~MessagePumpLibevent() { | 128 MessagePumpLibevent::~MessagePumpLibevent() { |
| 128 DCHECK(wakeup_event_); | 129 DCHECK(wakeup_event_); |
| 129 DCHECK(event_base_); | 130 DCHECK(event_base_); |
| 130 event_del(wakeup_event_); | 131 event_del(wakeup_event_); |
| 131 delete wakeup_event_; | 132 delete wakeup_event_; |
| 132 if (wakeup_pipe_in_ >= 0) { | 133 if (wakeup_pipe_in_ >= 0) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 } | 208 } |
| 208 | 209 |
| 209 void MessagePumpLibevent::AddIOObserver(IOObserver *obs) { | 210 void MessagePumpLibevent::AddIOObserver(IOObserver *obs) { |
| 210 io_observers_.AddObserver(obs); | 211 io_observers_.AddObserver(obs); |
| 211 } | 212 } |
| 212 | 213 |
| 213 void MessagePumpLibevent::RemoveIOObserver(IOObserver *obs) { | 214 void MessagePumpLibevent::RemoveIOObserver(IOObserver *obs) { |
| 214 io_observers_.RemoveObserver(obs); | 215 io_observers_.RemoveObserver(obs); |
| 215 } | 216 } |
| 216 | 217 |
| 218 void MessagePumpLibevent::SetEventSource(EventSource* event_source) { |
| 219 DCHECK(event_source); |
| 220 DCHECK(!event_source_ || event_source_ == event_source); |
| 221 event_source_ = event_source; |
| 222 } |
| 223 |
| 224 void MessagePumpLibevent::ClearEventSource() { |
| 225 event_source_ = nullptr; |
| 226 } |
| 227 |
| 217 // Tell libevent to break out of inner loop. | 228 // Tell libevent to break out of inner loop. |
| 218 static void timer_callback(int fd, short events, void *context) | 229 static void timer_callback(int fd, short events, void *context) |
| 219 { | 230 { |
| 220 event_base_loopbreak((struct event_base *)context); | 231 event_base_loopbreak((struct event_base *)context); |
| 221 } | 232 } |
| 222 | 233 |
| 223 // Reentrant! | 234 // Reentrant! |
| 224 void MessagePumpLibevent::Run(Delegate* delegate) { | 235 void MessagePumpLibevent::Run(Delegate* delegate) { |
| 225 AutoReset<bool> auto_reset_keep_running(&keep_running_, true); | 236 AutoReset<bool> auto_reset_keep_running(&keep_running_, true); |
| 226 AutoReset<bool> auto_reset_in_run(&in_run_, true); | 237 AutoReset<bool> auto_reset_in_run(&in_run_, true); |
| 227 | 238 |
| 228 // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641. | 239 // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641. |
| 229 // Instead, make our own timer and reuse it on each call to event_base_loop(). | 240 // Instead, make our own timer and reuse it on each call to event_base_loop(). |
| 230 scoped_ptr<event> timer_event(new event); | 241 scoped_ptr<event> timer_event(new event); |
| 231 | 242 |
| 232 for (;;) { | 243 for (;;) { |
| 233 #if defined(OS_MACOSX) | 244 #if defined(OS_MACOSX) |
| 234 mac::ScopedNSAutoreleasePool autorelease_pool; | 245 mac::ScopedNSAutoreleasePool autorelease_pool; |
| 235 #endif | 246 #endif |
| 236 | 247 |
| 237 bool did_work = delegate->DoWork(); | 248 bool did_work = delegate->DoWork(); |
| 238 if (!keep_running_) | 249 if (!keep_running_) |
| 239 break; | 250 break; |
| 240 | 251 |
| 252 did_work |= PollEventSource(); |
| 253 if (!keep_running_) |
| 254 break; |
| 255 |
| 241 event_base_loop(event_base_, EVLOOP_NONBLOCK); | 256 event_base_loop(event_base_, EVLOOP_NONBLOCK); |
| 242 did_work |= processed_io_events_; | 257 did_work |= processed_io_events_; |
| 243 processed_io_events_ = false; | 258 processed_io_events_ = false; |
| 244 if (!keep_running_) | 259 if (!keep_running_) |
| 245 break; | 260 break; |
| 246 | 261 |
| 247 did_work |= delegate->DoDelayedWork(&delayed_work_time_); | 262 did_work |= delegate->DoDelayedWork(&delayed_work_time_); |
| 248 if (!keep_running_) | 263 if (!keep_running_) |
| 249 break; | 264 break; |
| 250 | 265 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 } | 324 } |
| 310 | 325 |
| 311 void MessagePumpLibevent::WillProcessIOEvent() { | 326 void MessagePumpLibevent::WillProcessIOEvent() { |
| 312 FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent()); | 327 FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent()); |
| 313 } | 328 } |
| 314 | 329 |
| 315 void MessagePumpLibevent::DidProcessIOEvent() { | 330 void MessagePumpLibevent::DidProcessIOEvent() { |
| 316 FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent()); | 331 FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent()); |
| 317 } | 332 } |
| 318 | 333 |
| 334 bool MessagePumpLibevent::PollEventSource() { |
| 335 return event_source_ && event_source_->Poll(); |
| 336 } |
| 337 |
| 319 bool MessagePumpLibevent::Init() { | 338 bool MessagePumpLibevent::Init() { |
| 320 int fds[2]; | 339 int fds[2]; |
| 321 if (pipe(fds)) { | 340 if (pipe(fds)) { |
| 322 DLOG(ERROR) << "pipe() failed, errno: " << errno; | 341 DLOG(ERROR) << "pipe() failed, errno: " << errno; |
| 323 return false; | 342 return false; |
| 324 } | 343 } |
| 325 if (SetNonBlocking(fds[0])) { | 344 if (SetNonBlocking(fds[0])) { |
| 326 DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno; | 345 DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno; |
| 327 return false; | 346 return false; |
| 328 } | 347 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 // Remove and discard the wakeup byte. | 401 // Remove and discard the wakeup byte. |
| 383 char buf; | 402 char buf; |
| 384 int nread = HANDLE_EINTR(read(socket, &buf, 1)); | 403 int nread = HANDLE_EINTR(read(socket, &buf, 1)); |
| 385 DCHECK_EQ(nread, 1); | 404 DCHECK_EQ(nread, 1); |
| 386 that->processed_io_events_ = true; | 405 that->processed_io_events_ = true; |
| 387 // Tell libevent to break out of inner loop. | 406 // Tell libevent to break out of inner loop. |
| 388 event_base_loopbreak(that->event_base_); | 407 event_base_loopbreak(that->event_base_); |
| 389 } | 408 } |
| 390 | 409 |
| 391 } // namespace base | 410 } // namespace base |
| OLD | NEW |