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 <memory> 9 10 #include "base/compiler_specific.h" 11 #include "base/macros.h" 12 #include "base/message_loop/message_pump.h" 13 #include "base/message_loop/watchable_io_message_pump_posix.h" 14 #include "base/threading/thread_checker.h" 15 #include "base/time/time.h" 16 17 // Declare structs we need from libevent.h rather than including it 18 struct event_base; 19 struct event; 20 21 namespace base { 22 23 // Class to monitor sockets and issue callbacks when sockets are ready for I/O 24 // TODO(dkegel): add support for background file IO somehow 25 class BASE_EXPORT MessagePumpLibevent : public MessagePump, 26 public WatchableIOMessagePumpPosix { 27 public: 28 class FdWatchController : public FdWatchControllerInterface { 29 public: 30 explicit FdWatchController(const Location& from_here); 31 32 // Implicitly calls StopWatchingFileDescriptor. 33 ~FdWatchController() override; 34 35 // FdWatchControllerInterface: 36 bool StopWatchingFileDescriptor() override; 37 38 private: 39 friend class MessagePumpLibevent; 40 friend class MessagePumpLibeventTest; 41 42 // Called by MessagePumpLibevent. 43 void Init(std::unique_ptr<event> e); 44 45 // Used by MessagePumpLibevent to take ownership of |event_|. 46 std::unique_ptr<event> ReleaseEvent(); 47 set_pump(MessagePumpLibevent * pump)48 void set_pump(MessagePumpLibevent* pump) { pump_ = pump; } pump()49 MessagePumpLibevent* pump() const { return pump_; } 50 set_watcher(FdWatcher * watcher)51 void set_watcher(FdWatcher* watcher) { watcher_ = watcher; } 52 53 void OnFileCanReadWithoutBlocking(int fd, MessagePumpLibevent* pump); 54 void OnFileCanWriteWithoutBlocking(int fd, MessagePumpLibevent* pump); 55 56 std::unique_ptr<event> event_; 57 MessagePumpLibevent* pump_ = nullptr; 58 FdWatcher* watcher_ = nullptr; 59 // If this pointer is non-NULL, the pointee is set to true in the 60 // destructor. 61 bool* was_destroyed_ = nullptr; 62 63 DISALLOW_COPY_AND_ASSIGN(FdWatchController); 64 }; 65 66 MessagePumpLibevent(); 67 ~MessagePumpLibevent() override; 68 69 bool WatchFileDescriptor(int fd, 70 bool persistent, 71 int mode, 72 FdWatchController* controller, 73 FdWatcher* delegate); 74 75 // MessagePump methods: 76 void Run(Delegate* delegate) override; 77 void Quit() override; 78 void ScheduleWork() override; 79 void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; 80 81 private: 82 friend class MessagePumpLibeventTest; 83 84 // Risky part of constructor. Returns true on success. 85 bool Init(); 86 87 // Called by libevent to tell us a registered FD can be read/written to. 88 static void OnLibeventNotification(int fd, short flags, void* context); 89 90 // Unix pipe used to implement ScheduleWork() 91 // ... callback; called by libevent inside Run() when pipe is ready to read 92 static void OnWakeup(int socket, short flags, void* context); 93 94 // This flag is set to false when Run should return. 95 bool keep_running_; 96 97 // This flag is set when inside Run. 98 bool in_run_; 99 100 // This flag is set if libevent has processed I/O events. 101 bool processed_io_events_; 102 103 // The time at which we should call DoDelayedWork. 104 TimeTicks delayed_work_time_; 105 106 // Libevent dispatcher. Watches all sockets registered with it, and sends 107 // readiness callbacks when a socket is ready for I/O. 108 event_base* event_base_; 109 110 // ... write end; ScheduleWork() writes a single byte to it 111 int wakeup_pipe_in_; 112 // ... read end; OnWakeup reads it and then breaks Run() out of its sleep 113 int wakeup_pipe_out_; 114 // ... libevent wrapper for read end 115 event* wakeup_event_; 116 117 ThreadChecker watch_file_descriptor_caller_checker_; 118 DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent); 119 }; 120 121 } // namespace base 122 123 #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ 124