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