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: IOObserver()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: ~IOObserver()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: ~Watcher()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 set_pump(MessagePumpLibevent * pump)73 void set_pump(MessagePumpLibevent* pump) { pump_ = pump; } pump()74 MessagePumpLibevent* pump() { return pump_; } 75 set_watcher(Watcher * watcher)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