message_loop.h revision 58537e28ecd584eab876aee8be7156509866d23a
1// Copyright 2013 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_LOOP_H_ 6#define BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_ 7 8#include <queue> 9#include <string> 10 11#include "base/base_export.h" 12#include "base/basictypes.h" 13#include "base/callback_forward.h" 14#include "base/location.h" 15#include "base/memory/ref_counted.h" 16#include "base/memory/scoped_ptr.h" 17#include "base/message_loop/incoming_task_queue.h" 18#include "base/message_loop/message_loop_proxy.h" 19#include "base/message_loop/message_loop_proxy_impl.h" 20#include "base/message_loop/message_pump.h" 21#include "base/observer_list.h" 22#include "base/pending_task.h" 23#include "base/sequenced_task_runner_helpers.h" 24#include "base/synchronization/lock.h" 25#include "base/time/time.h" 26#include "base/tracking_info.h" 27 28#if defined(OS_WIN) 29// We need this to declare base::MessagePumpWin::Dispatcher, which we should 30// really just eliminate. 31#include "base/message_loop/message_pump_win.h" 32#elif defined(OS_IOS) 33#include "base/message_loop/message_pump_io_ios.h" 34#elif defined(OS_POSIX) 35#include "base/message_loop/message_pump_libevent.h" 36#if !defined(OS_MACOSX) && !defined(OS_ANDROID) 37 38#if defined(USE_AURA) && defined(USE_X11) && !defined(OS_NACL) 39#include "base/message_loop/message_pump_x11.h" 40#elif defined(USE_OZONE) && !defined(OS_NACL) 41#include "base/message_loop/message_pump_ozone.h" 42#else 43#define USE_GTK_MESSAGE_PUMP 44#include "base/message_loop/message_pump_gtk.h" 45#endif 46 47#endif 48#endif 49 50namespace base { 51 52class HistogramBase; 53class MessagePumpDispatcher; 54class MessagePumpObserver; 55class RunLoop; 56class ThreadTaskRunnerHandle; 57#if defined(OS_ANDROID) 58class MessagePumpForUI; 59#endif 60class WaitableEvent; 61 62// A MessageLoop is used to process events for a particular thread. There is 63// at most one MessageLoop instance per thread. 64// 65// Events include at a minimum Task instances submitted to PostTask and its 66// variants. Depending on the type of message pump used by the MessageLoop 67// other events such as UI messages may be processed. On Windows APC calls (as 68// time permits) and signals sent to a registered set of HANDLEs may also be 69// processed. 70// 71// NOTE: Unless otherwise specified, a MessageLoop's methods may only be called 72// on the thread where the MessageLoop's Run method executes. 73// 74// NOTE: MessageLoop has task reentrancy protection. This means that if a 75// task is being processed, a second task cannot start until the first task is 76// finished. Reentrancy can happen when processing a task, and an inner 77// message pump is created. That inner pump then processes native messages 78// which could implicitly start an inner task. Inner message pumps are created 79// with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions 80// (DoDragDrop), printer functions (StartDoc) and *many* others. 81// 82// Sample workaround when inner task processing is needed: 83// HRESULT hr; 84// { 85// MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); 86// hr = DoDragDrop(...); // Implicitly runs a modal message loop. 87// } 88// // Process |hr| (the result returned by DoDragDrop()). 89// 90// Please be SURE your task is reentrant (nestable) and all global variables 91// are stable and accessible before calling SetNestableTasksAllowed(true). 92// 93class BASE_EXPORT MessageLoop : public MessagePump::Delegate { 94 public: 95 96#if defined(USE_GTK_MESSAGE_PUMP) 97 typedef MessagePumpGdkObserver Observer; 98#elif !defined(OS_MACOSX) && !defined(OS_ANDROID) 99 typedef MessagePumpDispatcher Dispatcher; 100 typedef MessagePumpObserver Observer; 101#endif 102 103 // A MessageLoop has a particular type, which indicates the set of 104 // asynchronous events it may process in addition to tasks and timers. 105 // 106 // TYPE_DEFAULT 107 // This type of ML only supports tasks and timers. 108 // 109 // TYPE_UI 110 // This type of ML also supports native UI events (e.g., Windows messages). 111 // See also MessageLoopForUI. 112 // 113 // TYPE_IO 114 // This type of ML also supports asynchronous IO. See also 115 // MessageLoopForIO. 116 // 117 // TYPE_JAVA 118 // This type of ML is backed by a Java message handler which is responsible 119 // for running the tasks added to the ML. This is only for use on Android. 120 // TYPE_JAVA behaves in essence like TYPE_UI, except during construction 121 // where it does not use the main thread specific pump factory. 122 // 123 enum Type { 124 TYPE_DEFAULT, 125 TYPE_UI, 126 TYPE_IO, 127#if defined(OS_ANDROID) 128 TYPE_JAVA, 129#endif // defined(OS_ANDROID) 130 }; 131 132 // Normally, it is not necessary to instantiate a MessageLoop. Instead, it 133 // is typical to make use of the current thread's MessageLoop instance. 134 explicit MessageLoop(Type type = TYPE_DEFAULT); 135 virtual ~MessageLoop(); 136 137 // Returns the MessageLoop object for the current thread, or null if none. 138 static MessageLoop* current(); 139 140 static void EnableHistogrammer(bool enable_histogrammer); 141 142 typedef MessagePump* (MessagePumpFactory)(); 143 // Uses the given base::MessagePumpForUIFactory to override the default 144 // MessagePump implementation for 'TYPE_UI'. Returns true if the factory 145 // was successfully registered. 146 static bool InitMessagePumpForUIFactory(MessagePumpFactory* factory); 147 148 // A DestructionObserver is notified when the current MessageLoop is being 149 // destroyed. These observers are notified prior to MessageLoop::current() 150 // being changed to return NULL. This gives interested parties the chance to 151 // do final cleanup that depends on the MessageLoop. 152 // 153 // NOTE: Any tasks posted to the MessageLoop during this notification will 154 // not be run. Instead, they will be deleted. 155 // 156 class BASE_EXPORT DestructionObserver { 157 public: 158 virtual void WillDestroyCurrentMessageLoop() = 0; 159 160 protected: 161 virtual ~DestructionObserver(); 162 }; 163 164 // Add a DestructionObserver, which will start receiving notifications 165 // immediately. 166 void AddDestructionObserver(DestructionObserver* destruction_observer); 167 168 // Remove a DestructionObserver. It is safe to call this method while a 169 // DestructionObserver is receiving a notification callback. 170 void RemoveDestructionObserver(DestructionObserver* destruction_observer); 171 172 // The "PostTask" family of methods call the task's Run method asynchronously 173 // from within a message loop at some point in the future. 174 // 175 // With the PostTask variant, tasks are invoked in FIFO order, inter-mixed 176 // with normal UI or IO event processing. With the PostDelayedTask variant, 177 // tasks are called after at least approximately 'delay_ms' have elapsed. 178 // 179 // The NonNestable variants work similarly except that they promise never to 180 // dispatch the task from a nested invocation of MessageLoop::Run. Instead, 181 // such tasks get deferred until the top-most MessageLoop::Run is executing. 182 // 183 // The MessageLoop takes ownership of the Task, and deletes it after it has 184 // been Run(). 185 // 186 // PostTask(from_here, task) is equivalent to 187 // PostDelayedTask(from_here, task, 0). 188 // 189 // The TryPostTask is meant for the cases where the calling thread cannot 190 // block. If posting the task will block, the call returns false, the task 191 // is not posted but the task is consumed anyways. 192 // 193 // NOTE: These methods may be called on any thread. The Task will be invoked 194 // on the thread that executes MessageLoop::Run(). 195 void PostTask(const tracked_objects::Location& from_here, 196 const Closure& task); 197 198 bool TryPostTask(const tracked_objects::Location& from_here, 199 const Closure& task); 200 201 void PostDelayedTask(const tracked_objects::Location& from_here, 202 const Closure& task, 203 TimeDelta delay); 204 205 void PostNonNestableTask(const tracked_objects::Location& from_here, 206 const Closure& task); 207 208 void PostNonNestableDelayedTask(const tracked_objects::Location& from_here, 209 const Closure& task, 210 TimeDelta delay); 211 212 // A variant on PostTask that deletes the given object. This is useful 213 // if the object needs to live until the next run of the MessageLoop (for 214 // example, deleting a RenderProcessHost from within an IPC callback is not 215 // good). 216 // 217 // NOTE: This method may be called on any thread. The object will be deleted 218 // on the thread that executes MessageLoop::Run(). If this is not the same 219 // as the thread that calls PostDelayedTask(FROM_HERE, ), then T MUST inherit 220 // from RefCountedThreadSafe<T>! 221 template <class T> 222 void DeleteSoon(const tracked_objects::Location& from_here, const T* object) { 223 base::subtle::DeleteHelperInternal<T, void>::DeleteViaSequencedTaskRunner( 224 this, from_here, object); 225 } 226 227 // A variant on PostTask that releases the given reference counted object 228 // (by calling its Release method). This is useful if the object needs to 229 // live until the next run of the MessageLoop, or if the object needs to be 230 // released on a particular thread. 231 // 232 // NOTE: This method may be called on any thread. The object will be 233 // released (and thus possibly deleted) on the thread that executes 234 // MessageLoop::Run(). If this is not the same as the thread that calls 235 // PostDelayedTask(FROM_HERE, ), then T MUST inherit from 236 // RefCountedThreadSafe<T>! 237 template <class T> 238 void ReleaseSoon(const tracked_objects::Location& from_here, 239 const T* object) { 240 base::subtle::ReleaseHelperInternal<T, void>::ReleaseViaSequencedTaskRunner( 241 this, from_here, object); 242 } 243 244 // Deprecated: use RunLoop instead. 245 // Run the message loop. 246 void Run(); 247 248 // Deprecated: use RunLoop instead. 249 // Process all pending tasks, windows messages, etc., but don't wait/sleep. 250 // Return as soon as all items that can be run are taken care of. 251 void RunUntilIdle(); 252 253 // TODO(jbates) remove this. crbug.com/131220. See QuitWhenIdle(). 254 void Quit() { QuitWhenIdle(); } 255 256 // Deprecated: use RunLoop instead. 257 // 258 // Signals the Run method to return when it becomes idle. It will continue to 259 // process pending messages and future messages as long as they are enqueued. 260 // Warning: if the MessageLoop remains busy, it may never quit. Only use this 261 // Quit method when looping procedures (such as web pages) have been shut 262 // down. 263 // 264 // This method may only be called on the same thread that called Run, and Run 265 // must still be on the call stack. 266 // 267 // Use QuitClosure variants if you need to Quit another thread's MessageLoop, 268 // but note that doing so is fairly dangerous if the target thread makes 269 // nested calls to MessageLoop::Run. The problem being that you won't know 270 // which nested run loop you are quitting, so be careful! 271 void QuitWhenIdle(); 272 273 // Deprecated: use RunLoop instead. 274 // 275 // This method is a variant of Quit, that does not wait for pending messages 276 // to be processed before returning from Run. 277 void QuitNow(); 278 279 // TODO(jbates) remove this. crbug.com/131220. See QuitWhenIdleClosure(). 280 static Closure QuitClosure() { return QuitWhenIdleClosure(); } 281 282 // Deprecated: use RunLoop instead. 283 // Construct a Closure that will call QuitWhenIdle(). Useful to schedule an 284 // arbitrary MessageLoop to QuitWhenIdle. 285 static Closure QuitWhenIdleClosure(); 286 287 // Returns true if this loop is |type|. This allows subclasses (especially 288 // those in tests) to specialize how they are identified. 289 virtual bool IsType(Type type) const; 290 291 // Returns the type passed to the constructor. 292 Type type() const { return type_; } 293 294 // Optional call to connect the thread name with this loop. 295 void set_thread_name(const std::string& thread_name) { 296 DCHECK(thread_name_.empty()) << "Should not rename this thread!"; 297 thread_name_ = thread_name; 298 } 299 const std::string& thread_name() const { return thread_name_; } 300 301 // Gets the message loop proxy associated with this message loop. 302 scoped_refptr<MessageLoopProxy> message_loop_proxy() { 303 return message_loop_proxy_; 304 } 305 306 // Enables or disables the recursive task processing. This happens in the case 307 // of recursive message loops. Some unwanted message loop may occurs when 308 // using common controls or printer functions. By default, recursive task 309 // processing is disabled. 310 // 311 // Please utilize |ScopedNestableTaskAllower| instead of calling these methods 312 // directly. In general nestable message loops are to be avoided. They are 313 // dangerous and difficult to get right, so please use with extreme caution. 314 // 315 // The specific case where tasks get queued is: 316 // - The thread is running a message loop. 317 // - It receives a task #1 and execute it. 318 // - The task #1 implicitly start a message loop, like a MessageBox in the 319 // unit test. This can also be StartDoc or GetSaveFileName. 320 // - The thread receives a task #2 before or while in this second message 321 // loop. 322 // - With NestableTasksAllowed set to true, the task #2 will run right away. 323 // Otherwise, it will get executed right after task #1 completes at "thread 324 // message loop level". 325 void SetNestableTasksAllowed(bool allowed); 326 bool NestableTasksAllowed() const; 327 328 // Enables nestable tasks on |loop| while in scope. 329 class ScopedNestableTaskAllower { 330 public: 331 explicit ScopedNestableTaskAllower(MessageLoop* loop) 332 : loop_(loop), 333 old_state_(loop_->NestableTasksAllowed()) { 334 loop_->SetNestableTasksAllowed(true); 335 } 336 ~ScopedNestableTaskAllower() { 337 loop_->SetNestableTasksAllowed(old_state_); 338 } 339 340 private: 341 MessageLoop* loop_; 342 bool old_state_; 343 }; 344 345 // Enables or disables the restoration during an exception of the unhandled 346 // exception filter that was active when Run() was called. This can happen 347 // if some third party code call SetUnhandledExceptionFilter() and never 348 // restores the previous filter. 349 void set_exception_restoration(bool restore) { 350 exception_restoration_ = restore; 351 } 352 353 // Returns true if we are currently running a nested message loop. 354 bool IsNested(); 355 356 // A TaskObserver is an object that receives task notifications from the 357 // MessageLoop. 358 // 359 // NOTE: A TaskObserver implementation should be extremely fast! 360 class BASE_EXPORT TaskObserver { 361 public: 362 TaskObserver(); 363 364 // This method is called before processing a task. 365 virtual void WillProcessTask(const PendingTask& pending_task) = 0; 366 367 // This method is called after processing a task. 368 virtual void DidProcessTask(const PendingTask& pending_task) = 0; 369 370 protected: 371 virtual ~TaskObserver(); 372 }; 373 374 // These functions can only be called on the same thread that |this| is 375 // running on. 376 void AddTaskObserver(TaskObserver* task_observer); 377 void RemoveTaskObserver(TaskObserver* task_observer); 378 379 // When we go into high resolution timer mode, we will stay in hi-res mode 380 // for at least 1s. 381 static const int kHighResolutionTimerModeLeaseTimeMs = 1000; 382 383#if defined(OS_WIN) 384 void set_os_modal_loop(bool os_modal_loop) { 385 os_modal_loop_ = os_modal_loop; 386 } 387 388 bool os_modal_loop() const { 389 return os_modal_loop_; 390 } 391#endif // OS_WIN 392 393 // Can only be called from the thread that owns the MessageLoop. 394 bool is_running() const; 395 396 // Returns true if the message loop has high resolution timers enabled. 397 // Provided for testing. 398 bool IsHighResolutionTimerEnabledForTesting(); 399 400 // Returns true if the message loop is "idle". Provided for testing. 401 bool IsIdleForTesting(); 402 403 // Takes the incoming queue lock, signals |caller_wait| and waits until 404 // |caller_signal| is signalled. 405 void LockWaitUnLockForTesting(WaitableEvent* caller_wait, 406 WaitableEvent* caller_signal); 407 408 //---------------------------------------------------------------------------- 409 protected: 410 411#if defined(OS_WIN) 412 MessagePumpWin* pump_win() { 413 return static_cast<MessagePumpWin*>(pump_.get()); 414 } 415#elif defined(OS_POSIX) && !defined(OS_IOS) 416 MessagePumpLibevent* pump_libevent() { 417 return static_cast<MessagePumpLibevent*>(pump_.get()); 418 } 419#endif 420 421 scoped_ptr<MessagePump> pump_; 422 423 private: 424 friend class internal::IncomingTaskQueue; 425 friend class RunLoop; 426 427 // A function to encapsulate all the exception handling capability in the 428 // stacks around the running of a main message loop. It will run the message 429 // loop in a SEH try block or not depending on the set_SEH_restoration() 430 // flag invoking respectively RunInternalInSEHFrame() or RunInternal(). 431 void RunHandler(); 432 433#if defined(OS_WIN) 434 __declspec(noinline) void RunInternalInSEHFrame(); 435#endif 436 437 // A surrounding stack frame around the running of the message loop that 438 // supports all saving and restoring of state, as is needed for any/all (ugly) 439 // recursive calls. 440 void RunInternal(); 441 442 // Called to process any delayed non-nestable tasks. 443 bool ProcessNextDelayedNonNestableTask(); 444 445 // Runs the specified PendingTask. 446 void RunTask(const PendingTask& pending_task); 447 448 // Calls RunTask or queues the pending_task on the deferred task list if it 449 // cannot be run right now. Returns true if the task was run. 450 bool DeferOrRunPendingTask(const PendingTask& pending_task); 451 452 // Adds the pending task to delayed_work_queue_. 453 void AddToDelayedWorkQueue(const PendingTask& pending_task); 454 455 // Delete tasks that haven't run yet without running them. Used in the 456 // destructor to make sure all the task's destructors get called. Returns 457 // true if some work was done. 458 bool DeletePendingTasks(); 459 460 // Creates a process-wide unique ID to represent this task in trace events. 461 // This will be mangled with a Process ID hash to reduce the likelyhood of 462 // colliding with MessageLoop pointers on other processes. 463 uint64 GetTaskTraceID(const PendingTask& task); 464 465 // Loads tasks from the incoming queue to |work_queue_| if the latter is 466 // empty. 467 void ReloadWorkQueue(); 468 469 // Wakes up the message pump. Can be called on any thread. The caller is 470 // responsible for synchronizing ScheduleWork() calls. 471 void ScheduleWork(bool was_empty); 472 473 // Start recording histogram info about events and action IF it was enabled 474 // and IF the statistics recorder can accept a registration of our histogram. 475 void StartHistogrammer(); 476 477 // Add occurrence of event to our histogram, so that we can see what is being 478 // done in a specific MessageLoop instance (i.e., specific thread). 479 // If message_histogram_ is NULL, this is a no-op. 480 void HistogramEvent(int event); 481 482 // MessagePump::Delegate methods: 483 virtual bool DoWork() OVERRIDE; 484 virtual bool DoDelayedWork(TimeTicks* next_delayed_work_time) OVERRIDE; 485 virtual bool DoIdleWork() OVERRIDE; 486 virtual void GetQueueingInformation(size_t* queue_size, 487 TimeDelta* queueing_delay) OVERRIDE; 488 489 Type type_; 490 491 // A list of tasks that need to be processed by this instance. Note that 492 // this queue is only accessed (push/pop) by our current thread. 493 TaskQueue work_queue_; 494 495 // Contains delayed tasks, sorted by their 'delayed_run_time' property. 496 DelayedTaskQueue delayed_work_queue_; 497 498 // A recent snapshot of Time::Now(), used to check delayed_work_queue_. 499 TimeTicks recent_time_; 500 501 // A queue of non-nestable tasks that we had to defer because when it came 502 // time to execute them we were in a nested message loop. They will execute 503 // once we're out of nested message loops. 504 TaskQueue deferred_non_nestable_work_queue_; 505 506 ObserverList<DestructionObserver> destruction_observers_; 507 508 bool exception_restoration_; 509 510 // A recursion block that prevents accidentally running additional tasks when 511 // insider a (accidentally induced?) nested message pump. 512 bool nestable_tasks_allowed_; 513 514#if defined(OS_WIN) 515 // Should be set to true before calling Windows APIs like TrackPopupMenu, etc 516 // which enter a modal message loop. 517 bool os_modal_loop_; 518#endif 519 520 std::string thread_name_; 521 // A profiling histogram showing the counts of various messages and events. 522 HistogramBase* message_histogram_; 523 524 RunLoop* run_loop_; 525 526 ObserverList<TaskObserver> task_observers_; 527 528 scoped_refptr<internal::IncomingTaskQueue> incoming_task_queue_; 529 530 // The message loop proxy associated with this message loop. 531 scoped_refptr<internal::MessageLoopProxyImpl> message_loop_proxy_; 532 scoped_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_; 533 534 template <class T, class R> friend class base::subtle::DeleteHelperInternal; 535 template <class T, class R> friend class base::subtle::ReleaseHelperInternal; 536 537 void DeleteSoonInternal(const tracked_objects::Location& from_here, 538 void(*deleter)(const void*), 539 const void* object); 540 void ReleaseSoonInternal(const tracked_objects::Location& from_here, 541 void(*releaser)(const void*), 542 const void* object); 543 544 DISALLOW_COPY_AND_ASSIGN(MessageLoop); 545}; 546 547//----------------------------------------------------------------------------- 548// MessageLoopForUI extends MessageLoop with methods that are particular to a 549// MessageLoop instantiated with TYPE_UI. 550// 551// This class is typically used like so: 552// MessageLoopForUI::current()->...call some method... 553// 554class BASE_EXPORT MessageLoopForUI : public MessageLoop { 555 public: 556#if defined(OS_WIN) 557 typedef MessagePumpForUI::MessageFilter MessageFilter; 558#endif 559 560 MessageLoopForUI() : MessageLoop(TYPE_UI) { 561 } 562 563 // Returns the MessageLoopForUI of the current thread. 564 static MessageLoopForUI* current() { 565 MessageLoop* loop = MessageLoop::current(); 566 DCHECK(loop); 567 DCHECK_EQ(MessageLoop::TYPE_UI, loop->type()); 568 return static_cast<MessageLoopForUI*>(loop); 569 } 570 571#if defined(OS_WIN) 572 void DidProcessMessage(const MSG& message); 573#endif // defined(OS_WIN) 574 575#if defined(OS_IOS) 576 // On iOS, the main message loop cannot be Run(). Instead call Attach(), 577 // which connects this MessageLoop to the UI thread's CFRunLoop and allows 578 // PostTask() to work. 579 void Attach(); 580#endif 581 582#if defined(OS_ANDROID) 583 // On Android, the UI message loop is handled by Java side. So Run() should 584 // never be called. Instead use Start(), which will forward all the native UI 585 // events to the Java message loop. 586 void Start(); 587#elif !defined(OS_MACOSX) 588 589 // Please see message_pump_win/message_pump_glib for definitions of these 590 // methods. 591 void AddObserver(Observer* observer); 592 void RemoveObserver(Observer* observer); 593 594#if defined(OS_WIN) 595 // Plese see MessagePumpForUI for definitions of this method. 596 void SetMessageFilter(scoped_ptr<MessageFilter> message_filter) { 597 pump_ui()->SetMessageFilter(message_filter.Pass()); 598 } 599#endif 600 601 protected: 602#if defined(USE_AURA) && defined(USE_X11) && !defined(OS_NACL) 603 friend class MessagePumpX11; 604#endif 605#if defined(USE_OZONE) && !defined(OS_NACL) 606 friend class MessagePumpOzone; 607#endif 608 609 // TODO(rvargas): Make this platform independent. 610 MessagePumpForUI* pump_ui() { 611 return static_cast<MessagePumpForUI*>(pump_.get()); 612 } 613#endif // !defined(OS_MACOSX) 614}; 615 616// Do not add any member variables to MessageLoopForUI! This is important b/c 617// MessageLoopForUI is often allocated via MessageLoop(TYPE_UI). Any extra 618// data that you need should be stored on the MessageLoop's pump_ instance. 619COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForUI), 620 MessageLoopForUI_should_not_have_extra_member_variables); 621 622//----------------------------------------------------------------------------- 623// MessageLoopForIO extends MessageLoop with methods that are particular to a 624// MessageLoop instantiated with TYPE_IO. 625// 626// This class is typically used like so: 627// MessageLoopForIO::current()->...call some method... 628// 629class BASE_EXPORT MessageLoopForIO : public MessageLoop { 630 public: 631#if defined(OS_WIN) 632 typedef MessagePumpForIO::IOHandler IOHandler; 633 typedef MessagePumpForIO::IOContext IOContext; 634 typedef MessagePumpForIO::IOObserver IOObserver; 635#elif defined(OS_IOS) 636 typedef MessagePumpIOSForIO::Watcher Watcher; 637 typedef MessagePumpIOSForIO::FileDescriptorWatcher 638 FileDescriptorWatcher; 639 typedef MessagePumpIOSForIO::IOObserver IOObserver; 640 641 enum Mode { 642 WATCH_READ = MessagePumpIOSForIO::WATCH_READ, 643 WATCH_WRITE = MessagePumpIOSForIO::WATCH_WRITE, 644 WATCH_READ_WRITE = MessagePumpIOSForIO::WATCH_READ_WRITE 645 }; 646#elif defined(OS_POSIX) 647 typedef MessagePumpLibevent::Watcher Watcher; 648 typedef MessagePumpLibevent::FileDescriptorWatcher 649 FileDescriptorWatcher; 650 typedef MessagePumpLibevent::IOObserver IOObserver; 651 652 enum Mode { 653 WATCH_READ = MessagePumpLibevent::WATCH_READ, 654 WATCH_WRITE = MessagePumpLibevent::WATCH_WRITE, 655 WATCH_READ_WRITE = MessagePumpLibevent::WATCH_READ_WRITE 656 }; 657 658#endif 659 660 MessageLoopForIO() : MessageLoop(TYPE_IO) { 661 } 662 663 // Returns the MessageLoopForIO of the current thread. 664 static MessageLoopForIO* current() { 665 MessageLoop* loop = MessageLoop::current(); 666 DCHECK_EQ(MessageLoop::TYPE_IO, loop->type()); 667 return static_cast<MessageLoopForIO*>(loop); 668 } 669 670 void AddIOObserver(IOObserver* io_observer) { 671 pump_io()->AddIOObserver(io_observer); 672 } 673 674 void RemoveIOObserver(IOObserver* io_observer) { 675 pump_io()->RemoveIOObserver(io_observer); 676 } 677 678#if defined(OS_WIN) 679 // Please see MessagePumpWin for definitions of these methods. 680 void RegisterIOHandler(HANDLE file, IOHandler* handler); 681 bool RegisterJobObject(HANDLE job, IOHandler* handler); 682 bool WaitForIOCompletion(DWORD timeout, IOHandler* filter); 683 684 protected: 685 // TODO(rvargas): Make this platform independent. 686 MessagePumpForIO* pump_io() { 687 return static_cast<MessagePumpForIO*>(pump_.get()); 688 } 689 690#elif defined(OS_IOS) 691 // Please see MessagePumpIOSForIO for definition. 692 bool WatchFileDescriptor(int fd, 693 bool persistent, 694 Mode mode, 695 FileDescriptorWatcher *controller, 696 Watcher *delegate); 697 698 private: 699 MessagePumpIOSForIO* pump_io() { 700 return static_cast<MessagePumpIOSForIO*>(pump_.get()); 701 } 702 703#elif defined(OS_POSIX) 704 // Please see MessagePumpLibevent for definition. 705 bool WatchFileDescriptor(int fd, 706 bool persistent, 707 Mode mode, 708 FileDescriptorWatcher* controller, 709 Watcher* delegate); 710 711 private: 712 MessagePumpLibevent* pump_io() { 713 return static_cast<MessagePumpLibevent*>(pump_.get()); 714 } 715#endif // defined(OS_POSIX) 716}; 717 718// Do not add any member variables to MessageLoopForIO! This is important b/c 719// MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra 720// data that you need should be stored on the MessageLoop's pump_ instance. 721COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO), 722 MessageLoopForIO_should_not_have_extra_member_variables); 723 724} // namespace base 725 726#endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_ 727