1 : // Copyright (c) 2006-2008 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_PUMP_LIBEVENT_H_
6 : #define BASE_MESSAGE_PUMP_LIBEVENT_H_
7 :
8 : #include "base/message_pump.h"
9 : #include "base/time.h"
10 :
11 : // Declare structs we need from libevent.h rather than including it
12 : struct event_base;
13 : struct event;
14 :
15 : namespace base {
16 :
17 : // Class to monitor sockets and issue callbacks when sockets are ready for I/O
18 : // TODO(dkegel): add support for background file IO somehow
19 : class MessagePumpLibevent : public MessagePump {
20 : public:
21 :
22 : // Object returned by WatchFileDescriptor to manage further watching.
23 : class FileDescriptorWatcher {
24 : public:
25 : FileDescriptorWatcher();
26 : ~FileDescriptorWatcher(); // Implicitly calls StopWatchingFileDescriptor.
27 :
28 : // NOTE: These methods aren't called StartWatching()/StopWatching() to
29 : // avoid confusion with the win32 ObjectWatcher class.
30 :
31 : // Stop watching the FD, always safe to call. No-op if there's nothing
32 : // to do.
33 : bool StopWatchingFileDescriptor();
34 :
35 : private:
36 : // Called by MessagePumpLibevent, ownership of |e| is transferred to this
37 : // object.
38 : void Init(event* e, bool is_persistent);
39 :
40 : // Used by MessagePumpLibevent to take ownership of event_.
41 : event *ReleaseEvent();
42 : friend class MessagePumpLibevent;
43 :
44 : private:
45 : bool is_persistent_; // false if this event is one-shot.
46 : event* event_;
47 : DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher);
48 : };
49 :
50 : // Used with WatchFileDescptor to asynchronously monitor the I/O readiness of
51 : // a File Descriptor.
52 1 : class Watcher {
53 : public:
54 0 : virtual ~Watcher() {}
55 : // Called from MessageLoop::Run when an FD can be read from/written to
56 : // without blocking
57 : virtual void OnFileCanReadWithoutBlocking(int fd) = 0;
58 : virtual void OnFileCanWriteWithoutBlocking(int fd) = 0;
59 : };
60 :
61 : MessagePumpLibevent();
62 : virtual ~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,
82 : bool persistent,
83 : Mode mode,
84 : FileDescriptorWatcher *controller,
85 : Watcher *delegate);
86 :
87 :
88 : // This is analagous to FileDescriptorWatcher above, which really is
89 : // just a wrapper around libevent's |struct event|. This class acts
90 : // as a sort of "scoped event watcher" in that it guarantees that
91 : // when this class is out of scope, the signal-event it wraps is
92 : // removed from libevent's guts.
93 : //
94 : // XXX/cjones: this isn't my favorite API, but preserving it in
95 : // order to match code above
96 : class SignalEvent {
97 : friend class MessagePumpLibevent;
98 :
99 : public:
100 : SignalEvent();
101 : ~SignalEvent(); // implicitly calls StopCatching()
102 :
103 : // Have libevent forget this event.
104 : bool StopCatching();
105 :
106 : private:
107 : void Init(event* e);
108 : event* ReleaseEvent();
109 :
110 : event* event_;
111 :
112 : DISALLOW_COPY_AND_ASSIGN(SignalEvent);
113 : };
114 :
115 0 : class SignalWatcher {
116 : public:
117 0 : virtual ~SignalWatcher() {}
118 : // Called from MessageLoop::Run when |sig| has been delivered to
119 : // this process
120 : virtual void OnSignal(int sig) = 0;
121 : };
122 :
123 : // Have the current thread's message loop catch the signal |sig|.
124 : // Multiple watchers can catch the same signal; they're all notified
125 : // upon its delivery. Callers must provide a preallocated
126 : // SignalEvent object which can be used to manage the lifetime of
127 : // this event. Returns true on success.
128 : bool CatchSignal(int sig,
129 : SignalEvent* sigevent,
130 : SignalWatcher* delegate);
131 :
132 :
133 : // MessagePump methods:
134 : virtual void Run(Delegate* delegate);
135 : virtual void Quit();
136 : virtual void ScheduleWork();
137 : virtual void ScheduleDelayedWork(const Time& delayed_work_time);
138 :
139 : private:
140 :
141 : // Risky part of constructor. Returns true on success.
142 : bool Init();
143 :
144 : // This flag is set to false when Run should return.
145 : bool keep_running_;
146 :
147 : // This flag is set when inside Run.
148 : bool in_run_;
149 :
150 : // The time at which we should call DoDelayedWork.
151 : Time delayed_work_time_;
152 :
153 : // Libevent dispatcher. Watches all sockets registered with it, and sends
154 : // readiness callbacks when a socket is ready for I/O.
155 : event_base* event_base_;
156 :
157 : // Called by libevent to tell us a registered FD can be read/written to.
158 : static void OnLibeventNotification(int fd, short flags,
159 : void* context);
160 :
161 : // Called by libevent upon receiving a signal
162 : static void OnLibeventSignalNotification(int sig, short flags,
163 : void* context);
164 :
165 : // Unix pipe used to implement ScheduleWork()
166 : // ... callback; called by libevent inside Run() when pipe is ready to read
167 : static void OnWakeup(int socket, short flags, void* context);
168 : // ... write end; ScheduleWork() writes a single byte to it
169 : int wakeup_pipe_in_;
170 : // ... read end; OnWakeup reads it and then breaks Run() out of its sleep
171 : int wakeup_pipe_out_;
172 : // ... libevent wrapper for read end
173 : event* wakeup_event_;
174 :
175 : DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent);
176 : };
177 :
178 : } // namespace base
179 :
180 : #endif // BASE_MESSAGE_PUMP_LIBEVENT_H_
|