1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_pump_libevent.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h>
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <fcntl.h>
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/auto_reset.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/eintr_wrapper.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/mac/scoped_nsautorelease_pool.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/observer_list.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(USE_SYSTEM_LIBEVENT)
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <event.h>
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "third_party/libevent/event.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Lifecycle of struct event
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Libevent uses two main data structures:
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// struct event_base (of which there is one per message pump), and
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// struct event (of which there is roughly one per socket).
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The socket's struct event is created in
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// MessagePumpLibevent::WatchFileDescriptor(),
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// is owned by the FileDescriptorWatcher, and is destroyed in
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// StopWatchingFileDescriptor().
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// It is moved into and out of lists in struct event_base by
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the libevent functions event_add() and event_del().
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(dkegel):
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// At the moment bad things happen if a FileDescriptorWatcher
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// is active after its MessagePumpLibevent has been destroyed.
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// See MessageLoopTest.FileDescriptorWatcherOutlivesMessageLoop
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Not clear yet whether that situation occurs in practice,
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// but if it does, we need to fix it.
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base {
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Return 0 on success
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Too small a function to bother putting in a library?
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int SetNonBlocking(int fd) {
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int flags = fcntl(fd, F_GETFL, 0);
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (flags == -1)
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    flags = 0;
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher()
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : is_persistent_(false),
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      event_(NULL),
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      pump_(NULL),
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      watcher_(NULL) {
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() {
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_) {
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    StopWatchingFileDescriptor();
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() {
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  event* e = ReleaseEvent();
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (e == NULL)
6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return true;
6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // event_del() is a no-op if the event isn't active.
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int rv = event_del(e);
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  delete e;
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  pump_ = NULL;
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  watcher_ = NULL;
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return (rv == 0);
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::FileDescriptorWatcher::Init(event *e,
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                      bool is_persistent) {
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(e);
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!event_);
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  is_persistent_ = is_persistent;
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_ = e;
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottevent *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() {
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct event *e = event_;
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_ = NULL;
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return e;
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::FileDescriptorWatcher::OnFileCanReadWithoutBlocking(
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int fd, MessagePumpLibevent* pump) {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pump->WillProcessIOEvent();
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  watcher_->OnFileCanReadWithoutBlocking(fd);
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pump->DidProcessIOEvent();
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::FileDescriptorWatcher::OnFileCanWriteWithoutBlocking(
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int fd, MessagePumpLibevent* pump) {
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pump->WillProcessIOEvent();
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  watcher_->OnFileCanWriteWithoutBlocking(fd);
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pump->DidProcessIOEvent();
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpLibevent::MessagePumpLibevent()
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : keep_running_(true),
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      in_run_(false),
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      event_base_(event_base_new()),
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      wakeup_pipe_in_(-1),
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      wakeup_pipe_out_(-1) {
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!Init())
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     NOTREACHED();
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpLibevent::~MessagePumpLibevent() {
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(wakeup_event_);
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(event_base_);
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_del(wakeup_event_);
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delete wakeup_event_;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (wakeup_pipe_in_ >= 0) {
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (HANDLE_EINTR(close(wakeup_pipe_in_)) < 0)
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PLOG(ERROR) << "close";
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (wakeup_pipe_out_ >= 0) {
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (HANDLE_EINTR(close(wakeup_pipe_out_)) < 0)
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PLOG(ERROR) << "close";
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_base_free(event_base_);
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool MessagePumpLibevent::WatchFileDescriptor(int fd,
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                              bool persistent,
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                              Mode mode,
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                              FileDescriptorWatcher *controller,
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                              Watcher *delegate) {
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GE(fd, 0);
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(controller);
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(delegate);
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE);
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int event_mask = persistent ? EV_PERSIST : 0;
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if ((mode & WATCH_READ) != 0) {
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    event_mask |= EV_READ;
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if ((mode & WATCH_WRITE) != 0) {
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    event_mask |= EV_WRITE;
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<event> evt(controller->ReleaseEvent());
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (evt.get() == NULL) {
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Ownership is transferred to the controller.
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    evt.reset(new event);
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Make sure we don't pick up any funky internal libevent masks.
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int old_interest_mask = evt.get()->ev_events &
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        (EV_READ | EV_WRITE | EV_PERSIST);
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Combine old/new event masks.
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    event_mask |= old_interest_mask;
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Must disarm the event before we can reuse it.
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    event_del(evt.get());
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // It's illegal to use this function to listen on 2 separate fds with the
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // same |controller|.
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (EVENT_FD(evt.get()) != fd) {
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NOTREACHED() << "FDs don't match" << EVENT_FD(evt.get()) << "!=" << fd;
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Set current interest mask and message pump for this event.
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  event_set(evt.get(), fd, event_mask, OnLibeventNotification, controller);
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Tell libevent which message pump this socket will belong to when we add it.
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_base_set(event_base_, evt.get()) != 0) {
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Add this socket to the list of monitored sockets.
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_add(evt.get(), NULL) != 0) {
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Transfer ownership of evt to controller.
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  controller->Init(evt.release(), persistent);
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  controller->set_watcher(delegate);
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  controller->set_pump(this);
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MessagePumpLibevent::AddIOObserver(IOObserver *obs) {
19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  io_observers_.AddObserver(obs);
19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MessagePumpLibevent::RemoveIOObserver(IOObserver *obs) {
20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  io_observers_.RemoveObserver(obs);
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Tell libevent to break out of inner loop.
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void timer_callback(int fd, short events, void *context)
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_base_loopbreak((struct event_base *)context);
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Reentrant!
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::Run(Delegate* delegate) {
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(keep_running_) << "Quit must have been called outside of Run!";
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AutoReset<bool> auto_reset_in_run(&in_run_, true);
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641.
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Instead, make our own timer and reuse it on each call to event_base_loop().
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<event> timer_event(new event);
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (;;) {
220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    mac::ScopedNSAutoreleasePool autorelease_pool;
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool did_work = delegate->DoWork();
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!keep_running_)
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    did_work |= delegate->DoDelayedWork(&delayed_work_time_);
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!keep_running_)
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (did_work)
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    did_work = delegate->DoIdleWork();
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!keep_running_)
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (did_work)
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // EVLOOP_ONCE tells libevent to only block once,
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // but to service all pending events when it wakes up.
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (delayed_work_time_.is_null()) {
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      event_base_loop(event_base_, EVLOOP_ONCE);
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
245513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (delay > TimeDelta()) {
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        struct timeval poll_tv;
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        poll_tv.tv_sec = delay.InSeconds();
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond;
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        event_set(timer_event.get(), -1, 0, timer_callback, event_base_);
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        event_base_set(event_base_, timer_event.get());
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        event_add(timer_event.get(), &poll_tv);
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        event_base_loop(event_base_, EVLOOP_ONCE);
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        event_del(timer_event.get());
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // It looks like delayed_work_time_ indicates a time in the past, so we
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // need to call DoDelayedWork now.
258513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        delayed_work_time_ = TimeTicks();
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  keep_running_ = true;
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::Quit() {
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(in_run_);
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Tell both libevent and Run that they should break out of their loops.
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  keep_running_ = false;
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ScheduleWork();
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::ScheduleWork() {
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Tell libevent (in a threadsafe way) that it should break out of its loop.
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char buf = 0;
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int nwrite = HANDLE_EINTR(write(wakeup_pipe_in_, &buf, 1));
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(nwrite == 1 || errno == EAGAIN)
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      << "[nwrite:" << nwrite << "] [errno:" << errno << "]";
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
281513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid MessagePumpLibevent::ScheduleDelayedWork(
282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const TimeTicks& delayed_work_time) {
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We know that we can't be blocked on Wait right now since this method can
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // only be called on the same thread as Run, so we only need to update our
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // record of how long to sleep when we do sleep.
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delayed_work_time_ = delayed_work_time;
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::WillProcessIOEvent() {
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent());
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::DidProcessIOEvent() {
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent());
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool MessagePumpLibevent::Init() {
29872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int fds[2];
29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (pipe(fds)) {
30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DLOG(ERROR) << "pipe() failed, errno: " << errno;
30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (SetNonBlocking(fds[0])) {
30472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
30572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
30672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
30772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (SetNonBlocking(fds[1])) {
30872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
30972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
31072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
31172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  wakeup_pipe_out_ = fds[0];
31272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  wakeup_pipe_in_ = fds[1];
31372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  wakeup_event_ = new event;
31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST,
31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            OnWakeup, this);
31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  event_base_set(event_base_, wakeup_event_);
31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
31972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (event_add(wakeup_event_, 0))
32072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MessagePumpLibevent::OnLibeventNotification(int fd, short flags,
32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                 void* context) {
32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  FileDescriptorWatcher* controller =
32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      static_cast<FileDescriptorWatcher*>(context);
32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  MessagePumpLibevent* pump = controller->pump();
33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (flags & EV_WRITE) {
33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    controller->OnFileCanWriteWithoutBlocking(fd, pump);
33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (flags & EV_READ) {
33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    controller->OnFileCanReadWithoutBlocking(fd, pump);
33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Called if a byte is received on the wakeup pipe.
34172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
34272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) {
34372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::MessagePumpLibevent* that =
34472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              static_cast<base::MessagePumpLibevent*>(context);
34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(that->wakeup_pipe_out_ == socket);
34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Remove and discard the wakeup byte.
34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  char buf;
34972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int nread = HANDLE_EINTR(read(socket, &buf, 1));
35072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK_EQ(nread, 1);
35172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Tell libevent to break out of inner loop.
35272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  event_base_loopbreak(that->event_base_);
35372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace base
356