[email protected] | f2ebbf06 | 2012-04-06 03:14:30 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 59e69e74 | 2013-06-18 20:27:52 | [diff] [blame] | 5 | #ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ |
| 6 | #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 7 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 8 | #include "base/basictypes.h" |
[email protected] | b171946 | 2011-11-16 00:08:08 | [diff] [blame] | 9 | #include "base/compiler_specific.h" |
[email protected] | 8d5f3ac | 2011-07-20 16:01:32 | [diff] [blame] | 10 | #include "base/memory/weak_ptr.h" |
[email protected] | 59e69e74 | 2013-06-18 20:27:52 | [diff] [blame] | 11 | #include "base/message_loop/message_pump.h" |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 12 | #include "base/observer_list.h" |
[email protected] | b4339c3a | 2011-05-13 16:19:23 | [diff] [blame] | 13 | #include "base/threading/thread_checker.h" |
[email protected] | 99084f6 | 2013-06-28 00:49:07 | [diff] [blame] | 14 | #include "base/time/time.h" |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 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 |
[email protected] | 0bea725 | 2011-08-05 15:34:00 | [diff] [blame] | 24 | class BASE_EXPORT MessagePumpLibevent : public MessagePump { |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 25 | public: |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 26 | class IOObserver { |
| 27 | public: |
| 28 | IOObserver() {} |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 29 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 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; |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 36 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 37 | protected: |
| 38 | virtual ~IOObserver() {} |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 39 | }; |
| 40 | |
[email protected] | 8d5f3ac | 2011-07-20 16:01:32 | [diff] [blame] | 41 | // Used with WatchFileDescriptor to asynchronously monitor the I/O readiness |
| 42 | // of a file descriptor. |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 43 | class Watcher { |
| 44 | public: |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 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; |
[email protected] | cb93248 | 2012-06-26 06:23:00 | [diff] [blame] | 49 | |
| 50 | protected: |
| 51 | virtual ~Watcher() {} |
[email protected] | 1d2eb13 | 2008-12-08 17:36:06 | [diff] [blame] | 52 | }; |
| 53 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 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; |
[email protected] | 8d5f3ac | 2011-07-20 16:01:32 | [diff] [blame] | 69 | friend class MessagePumpLibeventTest; |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 70 | |
| 71 | // Called by MessagePumpLibevent, ownership of |e| is transferred to this |
| 72 | // object. |
[email protected] | 4b4047c4 | 2012-06-15 07:40:33 | [diff] [blame] | 73 | void Init(event* e); |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 74 | |
| 75 | // Used by MessagePumpLibevent to take ownership of event_. |
[email protected] | cb93248 | 2012-06-26 06:23:00 | [diff] [blame] | 76 | event* ReleaseEvent(); |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 77 | |
| 78 | void set_pump(MessagePumpLibevent* pump) { pump_ = pump; } |
[email protected] | d6bafc3 | 2012-11-30 17:29:40 | [diff] [blame] | 79 | MessagePumpLibevent* pump() const { return pump_; } |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 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 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 86 | event* event_; |
| 87 | MessagePumpLibevent* pump_; |
| 88 | Watcher* watcher_; |
[email protected] | 59e69e74 | 2013-06-18 20:27:52 | [diff] [blame] | 89 | WeakPtrFactory<FileDescriptorWatcher> weak_factory_; |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 90 | |
| 91 | DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher); |
| 92 | }; |
| 93 | |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 94 | enum Mode { |
| 95 | WATCH_READ = 1 << 0, |
| 96 | WATCH_WRITE = 1 << 1, |
| 97 | WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE |
| 98 | }; |
| 99 | |
[email protected] | a502bbe7 | 2011-01-07 18:06:45 | [diff] [blame] | 100 | MessagePumpLibevent(); |
dcheng | 5648818 | 2014-10-21 10:54:51 | [diff] [blame] | 101 | ~MessagePumpLibevent() override; |
[email protected] | a502bbe7 | 2011-01-07 18:06:45 | [diff] [blame] | 102 | |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 103 | // Have the current thread's message loop watch for a a situation in which |
[email protected] | 052fd45 | 2009-09-23 17:56:25 | [diff] [blame] | 104 | // reading/writing to the FD can be performed without blocking. |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 105 | // Callers must provide a preallocated FileDescriptorWatcher object which |
[email protected] | 052fd45 | 2009-09-23 17:56:25 | [diff] [blame] | 106 | // can later be used to manage the lifetime of this event. |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 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. |
[email protected] | 1d2eb13 | 2008-12-08 17:36:06 | [diff] [blame] | 112 | // Returns true on success. |
[email protected] | b4339c3a | 2011-05-13 16:19:23 | [diff] [blame] | 113 | // Must be called on the same thread the message_pump is running on. |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 114 | // TODO(dkegel): switch to edge-triggered readiness notification |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 115 | bool WatchFileDescriptor(int fd, |
| 116 | bool persistent, |
[email protected] | d6bafc3 | 2012-11-30 17:29:40 | [diff] [blame] | 117 | int mode, |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 118 | FileDescriptorWatcher *controller, |
| 119 | Watcher *delegate); |
[email protected] | 1d2eb13 | 2008-12-08 17:36:06 | [diff] [blame] | 120 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 121 | void AddIOObserver(IOObserver* obs); |
| 122 | void RemoveIOObserver(IOObserver* obs); |
| 123 | |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 124 | // MessagePump methods: |
dcheng | 5648818 | 2014-10-21 10:54:51 | [diff] [blame] | 125 | void Run(Delegate* delegate) override; |
| 126 | void Quit() override; |
| 127 | void ScheduleWork() override; |
| 128 | void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 129 | |
| 130 | private: |
[email protected] | 8d5f3ac | 2011-07-20 16:01:32 | [diff] [blame] | 131 | friend class MessagePumpLibeventTest; |
| 132 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 133 | void WillProcessIOEvent(); |
| 134 | void DidProcessIOEvent(); |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 135 | |
| 136 | // Risky part of constructor. Returns true on success. |
| 137 | bool Init(); |
| 138 | |
[email protected] | a502bbe7 | 2011-01-07 18:06:45 | [diff] [blame] | 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 | |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 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 | |
[email protected] | 4b4a94f22b | 2011-07-01 01:55:29 | [diff] [blame] | 153 | // This flag is set if libevent has processed I/O events. |
| 154 | bool processed_io_events_; |
| 155 | |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 156 | // The time at which we should call DoDelayedWork. |
[email protected] | 7e7fab4 | 2010-11-06 22:23:29 | [diff] [blame] | 157 | TimeTicks delayed_work_time_; |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 158 | |
[email protected] | 1d2eb13 | 2008-12-08 17:36:06 | [diff] [blame] | 159 | // Libevent dispatcher. Watches all sockets registered with it, and sends |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 160 | // readiness callbacks when a socket is ready for I/O. |
| 161 | event_base* event_base_; |
| 162 | |
[email protected] | 1d2eb13 | 2008-12-08 17:36:06 | [diff] [blame] | 163 | // ... write end; ScheduleWork() writes a single byte to it |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 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 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 170 | ObserverList<IOObserver> io_observers_; |
[email protected] | b4339c3a | 2011-05-13 16:19:23 | [diff] [blame] | 171 | ThreadChecker watch_file_descriptor_caller_checker_; |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 172 | DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent); |
| 173 | }; |
| 174 | |
| 175 | } // namespace base |
| 176 | |
[email protected] | 59e69e74 | 2013-06-18 20:27:52 | [diff] [blame] | 177 | #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ |