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