Home | History | Annotate | Download | only in base
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_MESSAGE_PUMP_LIBEVENT_H_
      6 #define BASE_MESSAGE_PUMP_LIBEVENT_H_
      7 #pragma once
      8 
      9 #include "base/basictypes.h"
     10 #include "base/message_pump.h"
     11 #include "base/observer_list.h"
     12 #include "base/time.h"
     13 
     14 // Declare structs we need from libevent.h rather than including it
     15 struct event_base;
     16 struct event;
     17 
     18 namespace base {
     19 
     20 // Class to monitor sockets and issue callbacks when sockets are ready for I/O
     21 // TODO(dkegel): add support for background file IO somehow
     22 class MessagePumpLibevent : public MessagePump {
     23  public:
     24   class IOObserver {
     25    public:
     26     IOObserver() {}
     27 
     28     // An IOObserver is an object that receives IO notifications from the
     29     // MessagePump.
     30     //
     31     // NOTE: An IOObserver implementation should be extremely fast!
     32     virtual void WillProcessIOEvent() = 0;
     33     virtual void DidProcessIOEvent() = 0;
     34 
     35    protected:
     36     virtual ~IOObserver() {}
     37   };
     38 
     39   // Used with WatchFileDescptor to asynchronously monitor the I/O readiness of
     40   // a File Descriptor.
     41   class Watcher {
     42    public:
     43     virtual ~Watcher() {}
     44     // Called from MessageLoop::Run when an FD can be read from/written to
     45     // without blocking
     46     virtual void OnFileCanReadWithoutBlocking(int fd) = 0;
     47     virtual void OnFileCanWriteWithoutBlocking(int fd) = 0;
     48   };
     49 
     50   // Object returned by WatchFileDescriptor to manage further watching.
     51   class FileDescriptorWatcher {
     52    public:
     53     FileDescriptorWatcher();
     54     ~FileDescriptorWatcher();  // Implicitly calls StopWatchingFileDescriptor.
     55 
     56     // NOTE: These methods aren't called StartWatching()/StopWatching() to
     57     // avoid confusion with the win32 ObjectWatcher class.
     58 
     59     // Stop watching the FD, always safe to call.  No-op if there's nothing
     60     // to do.
     61     bool StopWatchingFileDescriptor();
     62 
     63    private:
     64     friend class MessagePumpLibevent;
     65 
     66     // Called by MessagePumpLibevent, ownership of |e| is transferred to this
     67     // object.
     68     void Init(event* e, bool is_persistent);
     69 
     70     // Used by MessagePumpLibevent to take ownership of event_.
     71     event *ReleaseEvent();
     72 
     73     void set_pump(MessagePumpLibevent* pump) { pump_ = pump; }
     74     MessagePumpLibevent* pump() { return pump_; }
     75 
     76     void set_watcher(Watcher* watcher) { watcher_ = watcher; }
     77 
     78     void OnFileCanReadWithoutBlocking(int fd, MessagePumpLibevent* pump);
     79     void OnFileCanWriteWithoutBlocking(int fd, MessagePumpLibevent* pump);
     80 
     81     bool is_persistent_;  // false if this event is one-shot.
     82     event* event_;
     83     MessagePumpLibevent* pump_;
     84     Watcher* watcher_;
     85 
     86     DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher);
     87   };
     88 
     89   enum Mode {
     90     WATCH_READ = 1 << 0,
     91     WATCH_WRITE = 1 << 1,
     92     WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE
     93   };
     94 
     95   MessagePumpLibevent();
     96   virtual ~MessagePumpLibevent();
     97 
     98   // Have the current thread's message loop watch for a a situation in which
     99   // reading/writing to the FD can be performed without blocking.
    100   // Callers must provide a preallocated FileDescriptorWatcher object which
    101   // can later be used to manage the lifetime of this event.
    102   // If a FileDescriptorWatcher is passed in which is already attached to
    103   // an event, then the effect is cumulative i.e. after the call |controller|
    104   // will watch both the previous event and the new one.
    105   // If an error occurs while calling this method in a cumulative fashion, the
    106   // event previously attached to |controller| is aborted.
    107   // Returns true on success.
    108   // TODO(dkegel): switch to edge-triggered readiness notification
    109   bool WatchFileDescriptor(int fd,
    110                            bool persistent,
    111                            Mode mode,
    112                            FileDescriptorWatcher *controller,
    113                            Watcher *delegate);
    114 
    115   void AddIOObserver(IOObserver* obs);
    116   void RemoveIOObserver(IOObserver* obs);
    117 
    118   // MessagePump methods:
    119   virtual void Run(Delegate* delegate);
    120   virtual void Quit();
    121   virtual void ScheduleWork();
    122   virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time);
    123 
    124  private:
    125   void WillProcessIOEvent();
    126   void DidProcessIOEvent();
    127 
    128   // Risky part of constructor.  Returns true on success.
    129   bool Init();
    130 
    131   // Called by libevent to tell us a registered FD can be read/written to.
    132   static void OnLibeventNotification(int fd, short flags,
    133                                      void* context);
    134 
    135   // Unix pipe used to implement ScheduleWork()
    136   // ... callback; called by libevent inside Run() when pipe is ready to read
    137   static void OnWakeup(int socket, short flags, void* context);
    138 
    139   // This flag is set to false when Run should return.
    140   bool keep_running_;
    141 
    142   // This flag is set when inside Run.
    143   bool in_run_;
    144 
    145   // The time at which we should call DoDelayedWork.
    146   TimeTicks delayed_work_time_;
    147 
    148   // Libevent dispatcher.  Watches all sockets registered with it, and sends
    149   // readiness callbacks when a socket is ready for I/O.
    150   event_base* event_base_;
    151 
    152   // ... write end; ScheduleWork() writes a single byte to it
    153   int wakeup_pipe_in_;
    154   // ... read end; OnWakeup reads it and then breaks Run() out of its sleep
    155   int wakeup_pipe_out_;
    156   // ... libevent wrapper for read end
    157   event* wakeup_event_;
    158 
    159   ObserverList<IOObserver> io_observers_;
    160 
    161   DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent);
    162 };
    163 
    164 }  // namespace base
    165 
    166 #endif  // BASE_MESSAGE_PUMP_LIBEVENT_H_
    167