[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] | b171946 | 2011-11-16 00:08:08 | [diff] [blame] | 8 | #include "base/compiler_specific.h" |
ssid | 5dd4fb3 | 2017-02-16 23:57:17 | [diff] [blame] | 9 | #include "base/location.h" |
avi | 9b6f4293 | 2015-12-26 22:15:14 | [diff] [blame] | 10 | #include "base/macros.h" |
[email protected] | 59e69e74 | 2013-06-18 20:27:52 | [diff] [blame] | 11 | #include "base/message_loop/message_pump.h" |
[email protected] | b4339c3a | 2011-05-13 16:19:23 | [diff] [blame] | 12 | #include "base/threading/thread_checker.h" |
[email protected] | 99084f6 | 2013-06-28 00:49:07 | [diff] [blame] | 13 | #include "base/time/time.h" |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 14 | |
| 15 | // Declare structs we need from libevent.h rather than including it |
| 16 | struct event_base; |
| 17 | struct event; |
| 18 | |
| 19 | namespace base { |
| 20 | |
| 21 | // Class to monitor sockets and issue callbacks when sockets are ready for I/O |
| 22 | // TODO(dkegel): add support for background file IO somehow |
[email protected] | 0bea725 | 2011-08-05 15:34:00 | [diff] [blame] | 23 | class BASE_EXPORT MessagePumpLibevent : public MessagePump { |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 24 | public: |
[email protected] | 8d5f3ac | 2011-07-20 16:01:32 | [diff] [blame] | 25 | // Used with WatchFileDescriptor to asynchronously monitor the I/O readiness |
| 26 | // of a file descriptor. |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 27 | class Watcher { |
| 28 | public: |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 29 | // Called from MessageLoop::Run when an FD can be read from/written to |
| 30 | // without blocking |
| 31 | virtual void OnFileCanReadWithoutBlocking(int fd) = 0; |
| 32 | virtual void OnFileCanWriteWithoutBlocking(int fd) = 0; |
[email protected] | cb93248 | 2012-06-26 06:23:00 | [diff] [blame] | 33 | |
| 34 | protected: |
Chris Watkins | 091d629 | 2017-12-13 04:25:58 | [diff] [blame] | 35 | virtual ~Watcher() = default; |
[email protected] | 1d2eb13 | 2008-12-08 17:36:06 | [diff] [blame] | 36 | }; |
| 37 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 38 | // Object returned by WatchFileDescriptor to manage further watching. |
| 39 | class FileDescriptorWatcher { |
| 40 | public: |
Brett Wilson | 8e88b31 | 2017-09-12 05:22:16 | [diff] [blame] | 41 | explicit FileDescriptorWatcher(const Location& from_here); |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 42 | ~FileDescriptorWatcher(); // Implicitly calls StopWatchingFileDescriptor. |
| 43 | |
| 44 | // NOTE: These methods aren't called StartWatching()/StopWatching() to |
| 45 | // avoid confusion with the win32 ObjectWatcher class. |
| 46 | |
| 47 | // Stop watching the FD, always safe to call. No-op if there's nothing |
| 48 | // to do. |
| 49 | bool StopWatchingFileDescriptor(); |
| 50 | |
Brett Wilson | 8e88b31 | 2017-09-12 05:22:16 | [diff] [blame] | 51 | const Location& created_from_location() { return created_from_location_; } |
ssid | 5dd4fb3 | 2017-02-16 23:57:17 | [diff] [blame] | 52 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 53 | private: |
| 54 | friend class MessagePumpLibevent; |
[email protected] | 8d5f3ac | 2011-07-20 16:01:32 | [diff] [blame] | 55 | friend class MessagePumpLibeventTest; |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 56 | |
| 57 | // Called by MessagePumpLibevent, ownership of |e| is transferred to this |
| 58 | // object. |
[email protected] | 4b4047c4 | 2012-06-15 07:40:33 | [diff] [blame] | 59 | void Init(event* e); |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 60 | |
| 61 | // Used by MessagePumpLibevent to take ownership of event_. |
[email protected] | cb93248 | 2012-06-26 06:23:00 | [diff] [blame] | 62 | event* ReleaseEvent(); |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 63 | |
| 64 | void set_pump(MessagePumpLibevent* pump) { pump_ = pump; } |
[email protected] | d6bafc3 | 2012-11-30 17:29:40 | [diff] [blame] | 65 | MessagePumpLibevent* pump() const { return pump_; } |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 66 | |
| 67 | void set_watcher(Watcher* watcher) { watcher_ = watcher; } |
| 68 | |
| 69 | void OnFileCanReadWithoutBlocking(int fd, MessagePumpLibevent* pump); |
| 70 | void OnFileCanWriteWithoutBlocking(int fd, MessagePumpLibevent* pump); |
| 71 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 72 | event* event_; |
| 73 | MessagePumpLibevent* pump_; |
| 74 | Watcher* watcher_; |
ricea | 9ea8ee3 | 2015-08-06 08:19:06 | [diff] [blame] | 75 | // If this pointer is non-NULL, the pointee is set to true in the |
| 76 | // destructor. |
| 77 | bool* was_destroyed_; |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 78 | |
Brett Wilson | 8e88b31 | 2017-09-12 05:22:16 | [diff] [blame] | 79 | const Location created_from_location_; |
ssid | 5dd4fb3 | 2017-02-16 23:57:17 | [diff] [blame] | 80 | |
[email protected] | 9cfb89a | 2010-06-09 21:20:41 | [diff] [blame] | 81 | DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher); |
| 82 | }; |
| 83 | |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 84 | enum Mode { |
| 85 | WATCH_READ = 1 << 0, |
| 86 | WATCH_WRITE = 1 << 1, |
| 87 | WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE |
| 88 | }; |
| 89 | |
[email protected] | a502bbe7 | 2011-01-07 18:06:45 | [diff] [blame] | 90 | MessagePumpLibevent(); |
dcheng | 5648818 | 2014-10-21 10:54:51 | [diff] [blame] | 91 | ~MessagePumpLibevent() override; |
[email protected] | a502bbe7 | 2011-01-07 18:06:45 | [diff] [blame] | 92 | |
Luigi Semenzato | 516b5c81 | 2018-02-27 00:55:44 | [diff] [blame] | 93 | // Registers |delegate| with the current thread's message loop so that its |
| 94 | // methods are invoked when file descriptor |fd| becomes ready for reading or |
| 95 | // writing (or both) without blocking. |mode| selects ready for reading, for |
| 96 | // writing, or both. (See "enum Mode" above. TODO(unknown): nuke the |
| 97 | // plethora of equivalent "enum Mode" declarations.) |controller| manages |
| 98 | // the lifetime of registrations. ("Registrations" are also ambiguously |
| 99 | // called "events" in many places, for instance in libevent.) It is an error |
| 100 | // to use the same |controller| for different file descriptors; however, the |
| 101 | // same controller can be reused to add registrations with a different |
| 102 | // |mode|. If |controller| is already attached to one or more registrations, |
| 103 | // the new registration is added on to those. If an error occurs while |
| 104 | // calling this method, any registration previously attached to |controller| |
| 105 | // is removed. Returns true on success. Must be called on the same thread |
| 106 | // the message_pump is running on. |
[email protected] | e45e6c0 | 2008-12-15 22:02:17 | [diff] [blame] | 107 | bool WatchFileDescriptor(int fd, |
| 108 | bool persistent, |
[email protected] | d6bafc3 | 2012-11-30 17:29:40 | [diff] [blame] | 109 | int mode, |
tfarina | 87d123b | 2016-10-21 11:45:30 | [diff] [blame] | 110 | FileDescriptorWatcher* controller, |
| 111 | Watcher* delegate); |
[email protected] | 1d2eb13 | 2008-12-08 17:36:06 | [diff] [blame] | 112 | |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 113 | // MessagePump methods: |
dcheng | 5648818 | 2014-10-21 10:54:51 | [diff] [blame] | 114 | void Run(Delegate* delegate) override; |
| 115 | void Quit() override; |
| 116 | void ScheduleWork() override; |
| 117 | void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 118 | |
| 119 | private: |
[email protected] | 8d5f3ac | 2011-07-20 16:01:32 | [diff] [blame] | 120 | friend class MessagePumpLibeventTest; |
| 121 | |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 122 | // Risky part of constructor. Returns true on success. |
| 123 | bool Init(); |
| 124 | |
[email protected] | a502bbe7 | 2011-01-07 18:06:45 | [diff] [blame] | 125 | // Called by libevent to tell us a registered FD can be read/written to. |
tfarina | 87d123b | 2016-10-21 11:45:30 | [diff] [blame] | 126 | static void OnLibeventNotification(int fd, short flags, void* context); |
[email protected] | a502bbe7 | 2011-01-07 18:06:45 | [diff] [blame] | 127 | |
| 128 | // Unix pipe used to implement ScheduleWork() |
| 129 | // ... callback; called by libevent inside Run() when pipe is ready to read |
| 130 | static void OnWakeup(int socket, short flags, void* context); |
| 131 | |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 132 | // This flag is set to false when Run should return. |
| 133 | bool keep_running_; |
| 134 | |
| 135 | // This flag is set when inside Run. |
| 136 | bool in_run_; |
| 137 | |
[email protected] | 4b4a94f22b | 2011-07-01 01:55:29 | [diff] [blame] | 138 | // This flag is set if libevent has processed I/O events. |
| 139 | bool processed_io_events_; |
| 140 | |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 141 | // The time at which we should call DoDelayedWork. |
[email protected] | 7e7fab4 | 2010-11-06 22:23:29 | [diff] [blame] | 142 | TimeTicks delayed_work_time_; |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 143 | |
[email protected] | 1d2eb13 | 2008-12-08 17:36:06 | [diff] [blame] | 144 | // Libevent dispatcher. Watches all sockets registered with it, and sends |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 145 | // readiness callbacks when a socket is ready for I/O. |
| 146 | event_base* event_base_; |
| 147 | |
[email protected] | 1d2eb13 | 2008-12-08 17:36:06 | [diff] [blame] | 148 | // ... write end; ScheduleWork() writes a single byte to it |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 149 | int wakeup_pipe_in_; |
| 150 | // ... read end; OnWakeup reads it and then breaks Run() out of its sleep |
| 151 | int wakeup_pipe_out_; |
| 152 | // ... libevent wrapper for read end |
| 153 | event* wakeup_event_; |
| 154 | |
[email protected] | b4339c3a | 2011-05-13 16:19:23 | [diff] [blame] | 155 | ThreadChecker watch_file_descriptor_caller_checker_; |
[email protected] | 36987e9 | 2008-09-18 18:46:26 | [diff] [blame] | 156 | DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent); |
| 157 | }; |
| 158 | |
| 159 | } // namespace base |
| 160 | |
[email protected] | 59e69e74 | 2013-06-18 20:27:52 | [diff] [blame] | 161 | #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ |