1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/message_pump_libevent.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,215 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#ifndef BASE_MESSAGE_PUMP_LIBEVENT_H_ 1.9 +#define BASE_MESSAGE_PUMP_LIBEVENT_H_ 1.10 + 1.11 +#include "base/message_pump.h" 1.12 +#include "base/time.h" 1.13 +#include "nsAutoPtr.h" 1.14 + 1.15 +// Declare structs we need from libevent.h rather than including it 1.16 +struct event_base; 1.17 +struct event; 1.18 + 1.19 +class nsDependentCSubstring; 1.20 + 1.21 +namespace base { 1.22 + 1.23 +// Class to monitor sockets and issue callbacks when sockets are ready for I/O 1.24 +// TODO(dkegel): add support for background file IO somehow 1.25 +class MessagePumpLibevent : public MessagePump { 1.26 + public: 1.27 + 1.28 + // Object returned by WatchFileDescriptor to manage further watching. 1.29 + class FileDescriptorWatcher { 1.30 + public: 1.31 + FileDescriptorWatcher(); 1.32 + ~FileDescriptorWatcher(); // Implicitly calls StopWatchingFileDescriptor. 1.33 + 1.34 + // NOTE: These methods aren't called StartWatching()/StopWatching() to 1.35 + // avoid confusion with the win32 ObjectWatcher class. 1.36 + 1.37 + // Stop watching the FD, always safe to call. No-op if there's nothing 1.38 + // to do. 1.39 + bool StopWatchingFileDescriptor(); 1.40 + 1.41 + private: 1.42 + // Called by MessagePumpLibevent, ownership of |e| is transferred to this 1.43 + // object. 1.44 + void Init(event* e, bool is_persistent); 1.45 + 1.46 + // Used by MessagePumpLibevent to take ownership of event_. 1.47 + event *ReleaseEvent(); 1.48 + friend class MessagePumpLibevent; 1.49 + 1.50 + private: 1.51 + bool is_persistent_; // false if this event is one-shot. 1.52 + event* event_; 1.53 + DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher); 1.54 + }; 1.55 + 1.56 + // Used with WatchFileDescptor to asynchronously monitor the I/O readiness of 1.57 + // a File Descriptor. 1.58 + class Watcher { 1.59 + public: 1.60 + virtual ~Watcher() {} 1.61 + // Called from MessageLoop::Run when an FD can be read from/written to 1.62 + // without blocking 1.63 + virtual void OnFileCanReadWithoutBlocking(int fd) = 0; 1.64 + virtual void OnFileCanWriteWithoutBlocking(int fd) = 0; 1.65 + }; 1.66 + 1.67 + MessagePumpLibevent(); 1.68 + virtual ~MessagePumpLibevent(); 1.69 + 1.70 + enum Mode { 1.71 + WATCH_READ = 1 << 0, 1.72 + WATCH_WRITE = 1 << 1, 1.73 + WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE 1.74 + }; 1.75 + 1.76 + // Have the current thread's message loop watch for a a situation in which 1.77 + // reading/writing to the FD can be performed without Blocking. 1.78 + // Callers must provide a preallocated FileDescriptorWatcher object which 1.79 + // can later be used to manage the Lifetime of this event. 1.80 + // If a FileDescriptorWatcher is passed in which is already attached to 1.81 + // an event, then the effect is cumulative i.e. after the call |controller| 1.82 + // will watch both the previous event and the new one. 1.83 + // If an error occurs while calling this method in a cumulative fashion, the 1.84 + // event previously attached to |controller| is aborted. 1.85 + // Returns true on success. 1.86 + // TODO(dkegel): switch to edge-triggered readiness notification 1.87 + bool WatchFileDescriptor(int fd, 1.88 + bool persistent, 1.89 + Mode mode, 1.90 + FileDescriptorWatcher *controller, 1.91 + Watcher *delegate); 1.92 + 1.93 + 1.94 + // This is analagous to FileDescriptorWatcher above, which really is 1.95 + // just a wrapper around libevent's |struct event|. This class acts 1.96 + // as a sort of "scoped event watcher" in that it guarantees that 1.97 + // when this class is out of scope, the signal-event it wraps is 1.98 + // removed from libevent's guts. 1.99 + // 1.100 + // XXX/cjones: this isn't my favorite API, but preserving it in 1.101 + // order to match code above 1.102 + class SignalEvent { 1.103 + friend class MessagePumpLibevent; 1.104 + 1.105 + public: 1.106 + SignalEvent(); 1.107 + ~SignalEvent(); // implicitly calls StopCatching() 1.108 + 1.109 + // Have libevent forget this event. 1.110 + bool StopCatching(); 1.111 + 1.112 + private: 1.113 + void Init(event* e); 1.114 + event* ReleaseEvent(); 1.115 + 1.116 + event* event_; 1.117 + 1.118 + DISALLOW_COPY_AND_ASSIGN(SignalEvent); 1.119 + }; 1.120 + 1.121 + class SignalWatcher { 1.122 + public: 1.123 + virtual ~SignalWatcher() {} 1.124 + // Called from MessageLoop::Run when |sig| has been delivered to 1.125 + // this process 1.126 + virtual void OnSignal(int sig) = 0; 1.127 + }; 1.128 + 1.129 + // Have the current thread's message loop catch the signal |sig|. 1.130 + // Multiple watchers can catch the same signal; they're all notified 1.131 + // upon its delivery. Callers must provide a preallocated 1.132 + // SignalEvent object which can be used to manage the lifetime of 1.133 + // this event. Returns true on success. 1.134 + bool CatchSignal(int sig, 1.135 + SignalEvent* sigevent, 1.136 + SignalWatcher* delegate); 1.137 + 1.138 + 1.139 + // MessagePump methods: 1.140 + virtual void Run(Delegate* delegate); 1.141 + virtual void Quit(); 1.142 + virtual void ScheduleWork(); 1.143 + virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time); 1.144 + 1.145 + private: 1.146 + 1.147 + // Risky part of constructor. Returns true on success. 1.148 + bool Init(); 1.149 + 1.150 + // This flag is set to false when Run should return. 1.151 + bool keep_running_; 1.152 + 1.153 + // This flag is set when inside Run. 1.154 + bool in_run_; 1.155 + 1.156 + // The time at which we should call DoDelayedWork. 1.157 + TimeTicks delayed_work_time_; 1.158 + 1.159 + // Libevent dispatcher. Watches all sockets registered with it, and sends 1.160 + // readiness callbacks when a socket is ready for I/O. 1.161 + event_base* event_base_; 1.162 + 1.163 + // Called by libevent to tell us a registered FD can be read/written to. 1.164 + static void OnLibeventNotification(int fd, short flags, 1.165 + void* context); 1.166 + 1.167 + // Called by libevent upon receiving a signal 1.168 + static void OnLibeventSignalNotification(int sig, short flags, 1.169 + void* context); 1.170 + 1.171 + // Unix pipe used to implement ScheduleWork() 1.172 + // ... callback; called by libevent inside Run() when pipe is ready to read 1.173 + static void OnWakeup(int socket, short flags, void* context); 1.174 + // ... write end; ScheduleWork() writes a single byte to it 1.175 + int wakeup_pipe_in_; 1.176 + // ... read end; OnWakeup reads it and then breaks Run() out of its sleep 1.177 + int wakeup_pipe_out_; 1.178 + // ... libevent wrapper for read end 1.179 + event* wakeup_event_; 1.180 + 1.181 + DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent); 1.182 +}; 1.183 + 1.184 +/** 1.185 + * LineWatcher overrides OnFileCanReadWithoutBlocking. It separates the read 1.186 + * data by mTerminator and passes each line to OnLineRead. 1.187 + */ 1.188 +class LineWatcher : public MessagePumpLibevent::Watcher 1.189 +{ 1.190 +public: 1.191 + LineWatcher(char aTerminator, int aBufferSize) : mReceivedIndex(0), 1.192 + mBufferSize(aBufferSize), 1.193 + mTerminator(aTerminator) 1.194 + { 1.195 + mReceiveBuffer = new char[mBufferSize]; 1.196 + } 1.197 + 1.198 + ~LineWatcher() {} 1.199 + 1.200 +protected: 1.201 + /** 1.202 + * OnError will be called when |read| returns error. Derived class should 1.203 + * implement this function to handle error cases when needed. 1.204 + */ 1.205 + virtual void OnError() {} 1.206 + virtual void OnLineRead(int aFd, nsDependentCSubstring& aMessage) = 0; 1.207 + virtual void OnFileCanWriteWithoutBlocking(int /* aFd */) {} 1.208 +private: 1.209 + virtual void OnFileCanReadWithoutBlocking(int aFd) MOZ_FINAL; 1.210 + 1.211 + nsAutoPtr<char> mReceiveBuffer; 1.212 + int mReceivedIndex; 1.213 + int mBufferSize; 1.214 + char mTerminator; 1.215 +}; 1.216 +} // namespace base 1.217 + 1.218 +#endif // BASE_MESSAGE_PUMP_LIBEVENT_H_