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