message_pump_libevent.h (4843B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 #ifndef BASE_MESSAGE_PUMP_LIBEVENT_H_ 8 #define BASE_MESSAGE_PUMP_LIBEVENT_H_ 9 10 #include "base/message_pump.h" 11 #include "base/time.h" 12 13 // Declare structs we need from libevent.h rather than including it 14 struct event_base; 15 struct event; 16 17 namespace base { 18 19 // Class to monitor sockets and issue callbacks when sockets are ready for I/O 20 // TODO(dkegel): add support for background file IO somehow 21 class MessagePumpLibevent : public MessagePump { 22 public: 23 // Object returned by WatchFileDescriptor to manage further watching. 24 class FileDescriptorWatcher { 25 public: 26 FileDescriptorWatcher(); 27 ~FileDescriptorWatcher(); // Implicitly calls StopWatchingFileDescriptor. 28 29 // NOTE: These methods aren't called StartWatching()/StopWatching() to 30 // avoid confusion with the win32 ObjectWatcher class. 31 32 // Stop watching the FD, always safe to call. No-op if there's nothing 33 // to do. 34 bool StopWatchingFileDescriptor(); 35 36 private: 37 // Called by MessagePumpLibevent, ownership of |e| is transferred to this 38 // object. 39 void Init(event* e, bool is_persistent); 40 41 // Used by MessagePumpLibevent to take ownership of event_. 42 event* ReleaseEvent(); 43 friend class MessagePumpLibevent; 44 45 private: 46 bool is_persistent_; // false if this event is one-shot. 47 event* event_; 48 DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher); 49 }; 50 51 // Used with WatchFileDescptor to asynchronously monitor the I/O readiness of 52 // a File Descriptor. 53 class Watcher { 54 public: 55 virtual ~Watcher() {} 56 // Called from MessageLoop::Run when an FD can be read from/written to 57 // without blocking 58 virtual void OnFileCanReadWithoutBlocking(int fd) = 0; 59 virtual void OnFileCanWriteWithoutBlocking(int fd) = 0; 60 }; 61 62 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, bool persistent, Mode mode, 82 FileDescriptorWatcher* controller, 83 Watcher* delegate); 84 85 // MessagePump methods: 86 virtual void Run(Delegate* delegate) override; 87 virtual void Quit() override; 88 virtual void ScheduleWork() override; 89 virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; 90 91 protected: 92 virtual ~MessagePumpLibevent(); 93 94 private: 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 TimeTicks 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, void* context); 113 114 // Unix pipe used to implement ScheduleWork() 115 // ... callback; called by libevent inside Run() when pipe is ready to read 116 static void OnWakeup(int socket, short flags, void* context); 117 // ... write end; ScheduleWork() writes a single byte to it 118 int wakeup_pipe_in_; 119 // ... read end; OnWakeup reads it and then breaks Run() out of its sleep 120 int wakeup_pipe_out_; 121 // ... libevent wrapper for read end 122 event* wakeup_event_; 123 124 // Set to false when calling event_base_loop and to true when either of the 125 // OnWakeup, OnLibeventNotification or OnLibeventSignalNotification callbacks 126 // is called. 127 // Used to ensure our calls to profiler_thread_sleep and profiler_thread_wake 128 // are paired correctly. 129 static bool awake_; 130 131 DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent); 132 }; 133 134 } // namespace base 135 136 #endif // BASE_MESSAGE_PUMP_LIBEVENT_H_