|
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_LOOP_H_ |
|
6 #define BASE_MESSAGE_LOOP_H_ |
|
7 |
|
8 #include <deque> |
|
9 #include <queue> |
|
10 #include <string> |
|
11 #include <vector> |
|
12 |
|
13 #include <map> |
|
14 #include "base/lock.h" |
|
15 #include "base/message_pump.h" |
|
16 #include "base/observer_list.h" |
|
17 #include "base/ref_counted.h" |
|
18 #include "base/scoped_ptr.h" |
|
19 #include "base/task.h" |
|
20 #include "base/timer.h" |
|
21 |
|
22 #if defined(OS_WIN) |
|
23 // We need this to declare base::MessagePumpWin::Dispatcher, which we should |
|
24 // really just eliminate. |
|
25 #include "base/message_pump_win.h" |
|
26 #elif defined(OS_POSIX) |
|
27 #include "base/message_pump_libevent.h" |
|
28 #endif |
|
29 |
|
30 namespace mozilla { |
|
31 namespace ipc { |
|
32 |
|
33 class DoWorkRunnable; |
|
34 |
|
35 } /* namespace ipc */ |
|
36 } /* namespace mozilla */ |
|
37 |
|
38 // A MessageLoop is used to process events for a particular thread. There is |
|
39 // at most one MessageLoop instance per thread. |
|
40 // |
|
41 // Events include at a minimum Task instances submitted to PostTask or those |
|
42 // managed by TimerManager. Depending on the type of message pump used by the |
|
43 // MessageLoop other events such as UI messages may be processed. On Windows |
|
44 // APC calls (as time permits) and signals sent to a registered set of HANDLEs |
|
45 // may also be processed. |
|
46 // |
|
47 // NOTE: Unless otherwise specified, a MessageLoop's methods may only be called |
|
48 // on the thread where the MessageLoop's Run method executes. |
|
49 // |
|
50 // NOTE: MessageLoop has task reentrancy protection. This means that if a |
|
51 // task is being processed, a second task cannot start until the first task is |
|
52 // finished. Reentrancy can happen when processing a task, and an inner |
|
53 // message pump is created. That inner pump then processes native messages |
|
54 // which could implicitly start an inner task. Inner message pumps are created |
|
55 // with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions |
|
56 // (DoDragDrop), printer functions (StartDoc) and *many* others. |
|
57 // |
|
58 // Sample workaround when inner task processing is needed: |
|
59 // bool old_state = MessageLoop::current()->NestableTasksAllowed(); |
|
60 // MessageLoop::current()->SetNestableTasksAllowed(true); |
|
61 // HRESULT hr = DoDragDrop(...); // Implicitly runs a modal message loop here. |
|
62 // MessageLoop::current()->SetNestableTasksAllowed(old_state); |
|
63 // // Process hr (the result returned by DoDragDrop(). |
|
64 // |
|
65 // Please be SURE your task is reentrant (nestable) and all global variables |
|
66 // are stable and accessible before calling SetNestableTasksAllowed(true). |
|
67 // |
|
68 class MessageLoop : public base::MessagePump::Delegate { |
|
69 |
|
70 friend class mozilla::ipc::DoWorkRunnable; |
|
71 |
|
72 public: |
|
73 // A DestructionObserver is notified when the current MessageLoop is being |
|
74 // destroyed. These obsevers are notified prior to MessageLoop::current() |
|
75 // being changed to return NULL. This gives interested parties the chance to |
|
76 // do final cleanup that depends on the MessageLoop. |
|
77 // |
|
78 // NOTE: Any tasks posted to the MessageLoop during this notification will |
|
79 // not be run. Instead, they will be deleted. |
|
80 // |
|
81 class DestructionObserver { |
|
82 public: |
|
83 virtual ~DestructionObserver() {} |
|
84 virtual void WillDestroyCurrentMessageLoop() = 0; |
|
85 }; |
|
86 |
|
87 // Add a DestructionObserver, which will start receiving notifications |
|
88 // immediately. |
|
89 void AddDestructionObserver(DestructionObserver* destruction_observer); |
|
90 |
|
91 // Remove a DestructionObserver. It is safe to call this method while a |
|
92 // DestructionObserver is receiving a notification callback. |
|
93 void RemoveDestructionObserver(DestructionObserver* destruction_observer); |
|
94 |
|
95 // The "PostTask" family of methods call the task's Run method asynchronously |
|
96 // from within a message loop at some point in the future. |
|
97 // |
|
98 // With the PostTask variant, tasks are invoked in FIFO order, inter-mixed |
|
99 // with normal UI or IO event processing. With the PostDelayedTask variant, |
|
100 // tasks are called after at least approximately 'delay_ms' have elapsed. |
|
101 // |
|
102 // The NonNestable variants work similarly except that they promise never to |
|
103 // dispatch the task from a nested invocation of MessageLoop::Run. Instead, |
|
104 // such tasks get deferred until the top-most MessageLoop::Run is executing. |
|
105 // |
|
106 // The MessageLoop takes ownership of the Task, and deletes it after it has |
|
107 // been Run(). |
|
108 // |
|
109 // NOTE: These methods may be called on any thread. The Task will be invoked |
|
110 // on the thread that executes MessageLoop::Run(). |
|
111 |
|
112 void PostTask( |
|
113 const tracked_objects::Location& from_here, Task* task); |
|
114 |
|
115 void PostDelayedTask( |
|
116 const tracked_objects::Location& from_here, Task* task, int delay_ms); |
|
117 |
|
118 void PostNonNestableTask( |
|
119 const tracked_objects::Location& from_here, Task* task); |
|
120 |
|
121 void PostNonNestableDelayedTask( |
|
122 const tracked_objects::Location& from_here, Task* task, int delay_ms); |
|
123 |
|
124 // PostIdleTask is not thread safe and should be called on this thread |
|
125 void PostIdleTask( |
|
126 const tracked_objects::Location& from_here, Task* task); |
|
127 |
|
128 // A variant on PostTask that deletes the given object. This is useful |
|
129 // if the object needs to live until the next run of the MessageLoop (for |
|
130 // example, deleting a RenderProcessHost from within an IPC callback is not |
|
131 // good). |
|
132 // |
|
133 // NOTE: This method may be called on any thread. The object will be deleted |
|
134 // on the thread that executes MessageLoop::Run(). If this is not the same |
|
135 // as the thread that calls PostDelayedTask(FROM_HERE, ), then T MUST inherit |
|
136 // from RefCountedThreadSafe<T>! |
|
137 template <class T> |
|
138 void DeleteSoon(const tracked_objects::Location& from_here, T* object) { |
|
139 PostNonNestableTask(from_here, new DeleteTask<T>(object)); |
|
140 } |
|
141 |
|
142 // A variant on PostTask that releases the given reference counted object |
|
143 // (by calling its Release method). This is useful if the object needs to |
|
144 // live until the next run of the MessageLoop, or if the object needs to be |
|
145 // released on a particular thread. |
|
146 // |
|
147 // NOTE: This method may be called on any thread. The object will be |
|
148 // released (and thus possibly deleted) on the thread that executes |
|
149 // MessageLoop::Run(). If this is not the same as the thread that calls |
|
150 // PostDelayedTask(FROM_HERE, ), then T MUST inherit from |
|
151 // RefCountedThreadSafe<T>! |
|
152 template <class T> |
|
153 void ReleaseSoon(const tracked_objects::Location& from_here, T* object) { |
|
154 PostNonNestableTask(from_here, new ReleaseTask<T>(object)); |
|
155 } |
|
156 |
|
157 // Run the message loop. |
|
158 void Run(); |
|
159 |
|
160 // Process all pending tasks, windows messages, etc., but don't wait/sleep. |
|
161 // Return as soon as all items that can be run are taken care of. |
|
162 void RunAllPending(); |
|
163 |
|
164 // Signals the Run method to return after it is done processing all pending |
|
165 // messages. This method may only be called on the same thread that called |
|
166 // Run, and Run must still be on the call stack. |
|
167 // |
|
168 // Use QuitTask if you need to Quit another thread's MessageLoop, but note |
|
169 // that doing so is fairly dangerous if the target thread makes nested calls |
|
170 // to MessageLoop::Run. The problem being that you won't know which nested |
|
171 // run loop you are quiting, so be careful! |
|
172 // |
|
173 void Quit(); |
|
174 |
|
175 // Invokes Quit on the current MessageLoop when run. Useful to schedule an |
|
176 // arbitrary MessageLoop to Quit. |
|
177 class QuitTask : public Task { |
|
178 public: |
|
179 virtual void Run() { |
|
180 MessageLoop::current()->Quit(); |
|
181 } |
|
182 }; |
|
183 |
|
184 // A MessageLoop has a particular type, which indicates the set of |
|
185 // asynchronous events it may process in addition to tasks and timers. |
|
186 // |
|
187 // TYPE_DEFAULT |
|
188 // This type of ML only supports tasks and timers. |
|
189 // |
|
190 // TYPE_UI |
|
191 // This type of ML also supports native UI events (e.g., Windows messages). |
|
192 // See also MessageLoopForUI. |
|
193 // |
|
194 // TYPE_IO |
|
195 // This type of ML also supports asynchronous IO. See also |
|
196 // MessageLoopForIO. |
|
197 // |
|
198 // TYPE_MOZILLA_CHILD |
|
199 // This type of ML is used in Mozilla child processes which initialize |
|
200 // XPCOM and use the gecko event loop. |
|
201 // |
|
202 // TYPE_MOZILLA_UI |
|
203 // This type of ML is used in Mozilla parent processes which initialize |
|
204 // XPCOM and use the gecko event loop. |
|
205 // |
|
206 // TYPE_MOZILLA_NONMAINTHREAD |
|
207 // This type of ML is used in Mozilla parent processes which initialize |
|
208 // XPCOM and use the nsThread event loop. |
|
209 // |
|
210 enum Type { |
|
211 TYPE_DEFAULT, |
|
212 TYPE_UI, |
|
213 TYPE_IO, |
|
214 TYPE_MOZILLA_CHILD, |
|
215 TYPE_MOZILLA_UI, |
|
216 TYPE_MOZILLA_NONMAINTHREAD |
|
217 }; |
|
218 |
|
219 // Normally, it is not necessary to instantiate a MessageLoop. Instead, it |
|
220 // is typical to make use of the current thread's MessageLoop instance. |
|
221 explicit MessageLoop(Type type = TYPE_DEFAULT); |
|
222 ~MessageLoop(); |
|
223 |
|
224 // Returns the type passed to the constructor. |
|
225 Type type() const { return type_; } |
|
226 |
|
227 // Unique, non-repeating ID for this message loop. |
|
228 int32_t id() const { return id_; } |
|
229 |
|
230 // Optional call to connect the thread name with this loop. |
|
231 void set_thread_name(const std::string& thread_name) { |
|
232 DCHECK(thread_name_.empty()) << "Should not rename this thread!"; |
|
233 thread_name_ = thread_name; |
|
234 } |
|
235 const std::string& thread_name() const { return thread_name_; } |
|
236 |
|
237 // Returns the MessageLoop object for the current thread, or null if none. |
|
238 static MessageLoop* current(); |
|
239 |
|
240 // Enables or disables the recursive task processing. This happens in the case |
|
241 // of recursive message loops. Some unwanted message loop may occurs when |
|
242 // using common controls or printer functions. By default, recursive task |
|
243 // processing is disabled. |
|
244 // |
|
245 // The specific case where tasks get queued is: |
|
246 // - The thread is running a message loop. |
|
247 // - It receives a task #1 and execute it. |
|
248 // - The task #1 implicitly start a message loop, like a MessageBox in the |
|
249 // unit test. This can also be StartDoc or GetSaveFileName. |
|
250 // - The thread receives a task #2 before or while in this second message |
|
251 // loop. |
|
252 // - With NestableTasksAllowed set to true, the task #2 will run right away. |
|
253 // Otherwise, it will get executed right after task #1 completes at "thread |
|
254 // message loop level". |
|
255 void SetNestableTasksAllowed(bool allowed); |
|
256 void ScheduleWork(); |
|
257 bool NestableTasksAllowed() const; |
|
258 |
|
259 // Enables or disables the restoration during an exception of the unhandled |
|
260 // exception filter that was active when Run() was called. This can happen |
|
261 // if some third party code call SetUnhandledExceptionFilter() and never |
|
262 // restores the previous filter. |
|
263 void set_exception_restoration(bool restore) { |
|
264 exception_restoration_ = restore; |
|
265 } |
|
266 |
|
267 #if defined(OS_WIN) |
|
268 void set_os_modal_loop(bool os_modal_loop) { |
|
269 os_modal_loop_ = os_modal_loop; |
|
270 } |
|
271 |
|
272 bool & os_modal_loop() { |
|
273 return os_modal_loop_; |
|
274 } |
|
275 #endif // OS_WIN |
|
276 |
|
277 // Set the timeouts for background hang monitoring. |
|
278 // A value of 0 indicates there is no timeout. |
|
279 void set_hang_timeouts(uint32_t transient_timeout_ms, |
|
280 uint32_t permanent_timeout_ms) { |
|
281 transient_hang_timeout_ = transient_timeout_ms; |
|
282 permanent_hang_timeout_ = permanent_timeout_ms; |
|
283 } |
|
284 uint32_t transient_hang_timeout() const { |
|
285 return transient_hang_timeout_; |
|
286 } |
|
287 uint32_t permanent_hang_timeout() const { |
|
288 return permanent_hang_timeout_; |
|
289 } |
|
290 |
|
291 //---------------------------------------------------------------------------- |
|
292 protected: |
|
293 struct RunState { |
|
294 // Used to count how many Run() invocations are on the stack. |
|
295 int run_depth; |
|
296 |
|
297 // Used to record that Quit() was called, or that we should quit the pump |
|
298 // once it becomes idle. |
|
299 bool quit_received; |
|
300 |
|
301 #if defined(OS_WIN) |
|
302 base::MessagePumpWin::Dispatcher* dispatcher; |
|
303 #endif |
|
304 }; |
|
305 |
|
306 class AutoRunState : RunState { |
|
307 public: |
|
308 explicit AutoRunState(MessageLoop* loop); |
|
309 ~AutoRunState(); |
|
310 private: |
|
311 MessageLoop* loop_; |
|
312 RunState* previous_state_; |
|
313 }; |
|
314 |
|
315 // This structure is copied around by value. |
|
316 struct PendingTask { |
|
317 Task* task; // The task to run. |
|
318 base::TimeTicks delayed_run_time; // The time when the task should be run. |
|
319 int sequence_num; // Secondary sort key for run time. |
|
320 bool nestable; // OK to dispatch from a nested loop. |
|
321 |
|
322 PendingTask(Task* task, bool nestable) |
|
323 : task(task), sequence_num(0), nestable(nestable) { |
|
324 } |
|
325 |
|
326 // Used to support sorting. |
|
327 bool operator<(const PendingTask& other) const; |
|
328 }; |
|
329 |
|
330 typedef std::queue<PendingTask> TaskQueue; |
|
331 typedef std::priority_queue<PendingTask> DelayedTaskQueue; |
|
332 |
|
333 #if defined(OS_WIN) |
|
334 base::MessagePumpWin* pump_win() { |
|
335 return static_cast<base::MessagePumpWin*>(pump_.get()); |
|
336 } |
|
337 #elif defined(OS_POSIX) |
|
338 base::MessagePumpLibevent* pump_libevent() { |
|
339 return static_cast<base::MessagePumpLibevent*>(pump_.get()); |
|
340 } |
|
341 #endif |
|
342 |
|
343 // A function to encapsulate all the exception handling capability in the |
|
344 // stacks around the running of a main message loop. It will run the message |
|
345 // loop in a SEH try block or not depending on the set_SEH_restoration() |
|
346 // flag. |
|
347 void RunHandler(); |
|
348 |
|
349 // A surrounding stack frame around the running of the message loop that |
|
350 // supports all saving and restoring of state, as is needed for any/all (ugly) |
|
351 // recursive calls. |
|
352 void RunInternal(); |
|
353 |
|
354 // Called to process any delayed non-nestable tasks. |
|
355 bool ProcessNextDelayedNonNestableTask(); |
|
356 |
|
357 //---------------------------------------------------------------------------- |
|
358 // Run a work_queue_ task or new_task, and delete it (if it was processed by |
|
359 // PostTask). If there are queued tasks, the oldest one is executed and |
|
360 // new_task is queued. new_task is optional and can be NULL. In this NULL |
|
361 // case, the method will run one pending task (if any exist). Returns true if |
|
362 // it executes a task. Queued tasks accumulate only when there is a |
|
363 // non-nestable task currently processing, in which case the new_task is |
|
364 // appended to the list work_queue_. Such re-entrancy generally happens when |
|
365 // an unrequested message pump (typical of a native dialog) is executing in |
|
366 // the context of a task. |
|
367 bool QueueOrRunTask(Task* new_task); |
|
368 |
|
369 // Runs the specified task and deletes it. |
|
370 void RunTask(Task* task); |
|
371 |
|
372 // Calls RunTask or queues the pending_task on the deferred task list if it |
|
373 // cannot be run right now. Returns true if the task was run. |
|
374 bool DeferOrRunPendingTask(const PendingTask& pending_task); |
|
375 |
|
376 // Adds the pending task to delayed_work_queue_. |
|
377 void AddToDelayedWorkQueue(const PendingTask& pending_task); |
|
378 |
|
379 // Load tasks from the incoming_queue_ into work_queue_ if the latter is |
|
380 // empty. The former requires a lock to access, while the latter is directly |
|
381 // accessible on this thread. |
|
382 void ReloadWorkQueue(); |
|
383 |
|
384 // Delete tasks that haven't run yet without running them. Used in the |
|
385 // destructor to make sure all the task's destructors get called. Returns |
|
386 // true if some work was done. |
|
387 bool DeletePendingTasks(); |
|
388 |
|
389 // Post a task to our incomming queue. |
|
390 void PostTask_Helper(const tracked_objects::Location& from_here, Task* task, |
|
391 int delay_ms, bool nestable); |
|
392 |
|
393 // base::MessagePump::Delegate methods: |
|
394 virtual bool DoWork(); |
|
395 virtual bool DoDelayedWork(base::TimeTicks* next_delayed_work_time); |
|
396 virtual bool DoIdleWork(); |
|
397 |
|
398 Type type_; |
|
399 int32_t id_; |
|
400 |
|
401 // A list of tasks that need to be processed by this instance. Note that |
|
402 // this queue is only accessed (push/pop) by our current thread. |
|
403 TaskQueue work_queue_; |
|
404 |
|
405 // Contains delayed tasks, sorted by their 'delayed_run_time' property. |
|
406 DelayedTaskQueue delayed_work_queue_; |
|
407 |
|
408 // A queue of non-nestable tasks that we had to defer because when it came |
|
409 // time to execute them we were in a nested message loop. They will execute |
|
410 // once we're out of nested message loops. |
|
411 TaskQueue deferred_non_nestable_work_queue_; |
|
412 |
|
413 scoped_refptr<base::MessagePump> pump_; |
|
414 |
|
415 base::ObserverList<DestructionObserver> destruction_observers_; |
|
416 |
|
417 // A recursion block that prevents accidentally running additonal tasks when |
|
418 // insider a (accidentally induced?) nested message pump. |
|
419 bool nestable_tasks_allowed_; |
|
420 |
|
421 bool exception_restoration_; |
|
422 |
|
423 std::string thread_name_; |
|
424 |
|
425 // A null terminated list which creates an incoming_queue of tasks that are |
|
426 // aquired under a mutex for processing on this instance's thread. These tasks |
|
427 // have not yet been sorted out into items for our work_queue_ vs items that |
|
428 // will be handled by the TimerManager. |
|
429 TaskQueue incoming_queue_; |
|
430 // Protect access to incoming_queue_. |
|
431 Lock incoming_queue_lock_; |
|
432 |
|
433 RunState* state_; |
|
434 int run_depth_base_; |
|
435 |
|
436 #if defined(OS_WIN) |
|
437 // Should be set to true before calling Windows APIs like TrackPopupMenu, etc |
|
438 // which enter a modal message loop. |
|
439 bool os_modal_loop_; |
|
440 #endif |
|
441 |
|
442 // Timeout values for hang monitoring |
|
443 uint32_t transient_hang_timeout_; |
|
444 uint32_t permanent_hang_timeout_; |
|
445 |
|
446 // The next sequence number to use for delayed tasks. |
|
447 int next_sequence_num_; |
|
448 |
|
449 DISALLOW_COPY_AND_ASSIGN(MessageLoop); |
|
450 }; |
|
451 |
|
452 //----------------------------------------------------------------------------- |
|
453 // MessageLoopForUI extends MessageLoop with methods that are particular to a |
|
454 // MessageLoop instantiated with TYPE_UI. |
|
455 // |
|
456 // This class is typically used like so: |
|
457 // MessageLoopForUI::current()->...call some method... |
|
458 // |
|
459 class MessageLoopForUI : public MessageLoop { |
|
460 public: |
|
461 MessageLoopForUI(Type type=TYPE_UI) : MessageLoop(type) { |
|
462 } |
|
463 |
|
464 // Returns the MessageLoopForUI of the current thread. |
|
465 static MessageLoopForUI* current() { |
|
466 MessageLoop* loop = MessageLoop::current(); |
|
467 if (!loop) |
|
468 return NULL; |
|
469 Type type = loop->type(); |
|
470 DCHECK(type == MessageLoop::TYPE_UI || |
|
471 type == MessageLoop::TYPE_MOZILLA_UI || |
|
472 type == MessageLoop::TYPE_MOZILLA_CHILD); |
|
473 return static_cast<MessageLoopForUI*>(loop); |
|
474 } |
|
475 |
|
476 #if defined(OS_WIN) |
|
477 typedef base::MessagePumpWin::Dispatcher Dispatcher; |
|
478 typedef base::MessagePumpWin::Observer Observer; |
|
479 |
|
480 // Please see MessagePumpWin for definitions of these methods. |
|
481 void Run(Dispatcher* dispatcher); |
|
482 void AddObserver(Observer* observer); |
|
483 void RemoveObserver(Observer* observer); |
|
484 void WillProcessMessage(const MSG& message); |
|
485 void DidProcessMessage(const MSG& message); |
|
486 void PumpOutPendingPaintMessages(); |
|
487 |
|
488 protected: |
|
489 // TODO(rvargas): Make this platform independent. |
|
490 base::MessagePumpForUI* pump_ui() { |
|
491 return static_cast<base::MessagePumpForUI*>(pump_.get()); |
|
492 } |
|
493 #endif // defined(OS_WIN) |
|
494 }; |
|
495 |
|
496 // Do not add any member variables to MessageLoopForUI! This is important b/c |
|
497 // MessageLoopForUI is often allocated via MessageLoop(TYPE_UI). Any extra |
|
498 // data that you need should be stored on the MessageLoop's pump_ instance. |
|
499 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForUI), |
|
500 MessageLoopForUI_should_not_have_extra_member_variables); |
|
501 |
|
502 //----------------------------------------------------------------------------- |
|
503 // MessageLoopForIO extends MessageLoop with methods that are particular to a |
|
504 // MessageLoop instantiated with TYPE_IO. |
|
505 // |
|
506 // This class is typically used like so: |
|
507 // MessageLoopForIO::current()->...call some method... |
|
508 // |
|
509 class MessageLoopForIO : public MessageLoop { |
|
510 public: |
|
511 MessageLoopForIO() : MessageLoop(TYPE_IO) { |
|
512 } |
|
513 |
|
514 // Returns the MessageLoopForIO of the current thread. |
|
515 static MessageLoopForIO* current() { |
|
516 MessageLoop* loop = MessageLoop::current(); |
|
517 DCHECK_EQ(MessageLoop::TYPE_IO, loop->type()); |
|
518 return static_cast<MessageLoopForIO*>(loop); |
|
519 } |
|
520 |
|
521 #if defined(OS_WIN) |
|
522 typedef base::MessagePumpForIO::IOHandler IOHandler; |
|
523 typedef base::MessagePumpForIO::IOContext IOContext; |
|
524 |
|
525 // Please see MessagePumpWin for definitions of these methods. |
|
526 void RegisterIOHandler(HANDLE file_handle, IOHandler* handler); |
|
527 bool WaitForIOCompletion(DWORD timeout, IOHandler* filter); |
|
528 |
|
529 protected: |
|
530 // TODO(rvargas): Make this platform independent. |
|
531 base::MessagePumpForIO* pump_io() { |
|
532 return static_cast<base::MessagePumpForIO*>(pump_.get()); |
|
533 } |
|
534 |
|
535 #elif defined(OS_POSIX) |
|
536 typedef base::MessagePumpLibevent::Watcher Watcher; |
|
537 typedef base::MessagePumpLibevent::FileDescriptorWatcher |
|
538 FileDescriptorWatcher; |
|
539 typedef base::LineWatcher LineWatcher; |
|
540 |
|
541 enum Mode { |
|
542 WATCH_READ = base::MessagePumpLibevent::WATCH_READ, |
|
543 WATCH_WRITE = base::MessagePumpLibevent::WATCH_WRITE, |
|
544 WATCH_READ_WRITE = base::MessagePumpLibevent::WATCH_READ_WRITE |
|
545 }; |
|
546 |
|
547 // Please see MessagePumpLibevent for definition. |
|
548 bool WatchFileDescriptor(int fd, |
|
549 bool persistent, |
|
550 Mode mode, |
|
551 FileDescriptorWatcher *controller, |
|
552 Watcher *delegate); |
|
553 |
|
554 typedef base::MessagePumpLibevent::SignalEvent SignalEvent; |
|
555 typedef base::MessagePumpLibevent::SignalWatcher SignalWatcher; |
|
556 bool CatchSignal(int sig, |
|
557 SignalEvent* sigevent, |
|
558 SignalWatcher* delegate); |
|
559 |
|
560 #endif // defined(OS_POSIX) |
|
561 }; |
|
562 |
|
563 // Do not add any member variables to MessageLoopForIO! This is important b/c |
|
564 // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra |
|
565 // data that you need should be stored on the MessageLoop's pump_ instance. |
|
566 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO), |
|
567 MessageLoopForIO_should_not_have_extra_member_variables); |
|
568 |
|
569 #endif // BASE_MESSAGE_LOOP_H_ |