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