1 // Copyright (c) 2012 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_PUMP_H_ 6 #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_ 7 8 #include "base/base_export.h" 9 #include "base/basictypes.h" 10 #include "base/message_loop/timer_slack.h" 11 #include "base/threading/non_thread_safe.h" 12 13 namespace base { 14 15 class TimeDelta; 16 class TimeTicks; 17 18 class BASE_EXPORT MessagePump : public NonThreadSafe { 19 public: 20 // Please see the comments above the Run method for an illustration of how 21 // these delegate methods are used. 22 class BASE_EXPORT Delegate { 23 public: 24 virtual ~Delegate() {} 25 26 // Called from within Run in response to ScheduleWork or when the message 27 // pump would otherwise call DoDelayedWork. Returns true to indicate that 28 // work was done. DoDelayedWork will still be called if DoWork returns 29 // true, but DoIdleWork will not. 30 virtual bool DoWork() = 0; 31 32 // Called from within Run in response to ScheduleDelayedWork or when the 33 // message pump would otherwise sleep waiting for more work. Returns true 34 // to indicate that delayed work was done. DoIdleWork will not be called 35 // if DoDelayedWork returns true. Upon return |next_delayed_work_time| 36 // indicates the time when DoDelayedWork should be called again. If 37 // |next_delayed_work_time| is null (per Time::is_null), then the queue of 38 // future delayed work (timer events) is currently empty, and no additional 39 // calls to this function need to be scheduled. 40 virtual bool DoDelayedWork(TimeTicks* next_delayed_work_time) = 0; 41 42 // Called from within Run just before the message pump goes to sleep. 43 // Returns true to indicate that idle work was done. 44 virtual bool DoIdleWork() = 0; 45 46 // Via the two required out pointers, returns the length of the Delegate's 47 // work queue and the length of time that the first item in the queue has 48 // been waiting to run. If the work queue is empty, the count and delay 49 // will both be zero. 50 // Note that this only counts the tasks in the ready-to-run queue and not 51 // the incoming queue that is used by other threads to post tasks. The 52 // latter queue requires holding a lock, which is deemed too expensive for 53 // instrumentation code. Under normal conditions, the incoming queue should 54 // be small or zero, but under heavy loads it may be much larger and 55 // |queue_count| may be up to 1/4 the size of the incoming queue. 56 virtual void GetQueueingInformation(size_t* queue_count, 57 TimeDelta* queueing_delay) {} 58 }; 59 60 MessagePump(); 61 virtual ~MessagePump(); 62 63 // The Run method is called to enter the message pump's run loop. 64 // 65 // Within the method, the message pump is responsible for processing native 66 // messages as well as for giving cycles to the delegate periodically. The 67 // message pump should take care to mix delegate callbacks with native 68 // message processing so neither type of event starves the other of cycles. 69 // 70 // The anatomy of a typical run loop: 71 // 72 // for (;;) { 73 // bool did_work = DoInternalWork(); 74 // if (should_quit_) 75 // break; 76 // 77 // did_work |= delegate_->DoWork(); 78 // if (should_quit_) 79 // break; 80 // 81 // TimeTicks next_time; 82 // did_work |= delegate_->DoDelayedWork(&next_time); 83 // if (should_quit_) 84 // break; 85 // 86 // if (did_work) 87 // continue; 88 // 89 // did_work = delegate_->DoIdleWork(); 90 // if (should_quit_) 91 // break; 92 // 93 // if (did_work) 94 // continue; 95 // 96 // WaitForWork(); 97 // } 98 // 99 // Here, DoInternalWork is some private method of the message pump that is 100 // responsible for dispatching the next UI message or notifying the next IO 101 // completion (for example). WaitForWork is a private method that simply 102 // blocks until there is more work of any type to do. 103 // 104 // Notice that the run loop cycles between calling DoInternalWork, DoWork, 105 // and DoDelayedWork methods. This helps ensure that none of these work 106 // queues starve the others. This is important for message pumps that are 107 // used to drive animations, for example. 108 // 109 // Notice also that after each callout to foreign code, the run loop checks 110 // to see if it should quit. The Quit method is responsible for setting this 111 // flag. No further work is done once the quit flag is set. 112 // 113 // NOTE: Care must be taken to handle Run being called again from within any 114 // of the callouts to foreign code. Native message pumps may also need to 115 // deal with other native message pumps being run outside their control 116 // (e.g., the MessageBox API on Windows pumps UI messages!). To be specific, 117 // the callouts (DoWork and DoDelayedWork) MUST still be provided even in 118 // nested sub-loops that are "seemingly" outside the control of this message 119 // pump. DoWork in particular must never be starved for time slices unless 120 // it returns false (meaning it has run out of things to do). 121 // 122 virtual void Run(Delegate* delegate) = 0; 123 124 // Quit immediately from the most recently entered run loop. This method may 125 // only be used on the thread that called Run. 126 virtual void Quit() = 0; 127 128 // Schedule a DoWork callback to happen reasonably soon. Does nothing if a 129 // DoWork callback is already scheduled. This method may be called from any 130 // thread. Once this call is made, DoWork should not be "starved" at least 131 // until it returns a value of false. 132 virtual void ScheduleWork() = 0; 133 134 // Schedule a DoDelayedWork callback to happen at the specified time, 135 // cancelling any pending DoDelayedWork callback. This method may only be 136 // used on the thread that called Run. 137 virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) = 0; 138 139 // Sets the timer slack to the specified value. 140 virtual void SetTimerSlack(TimerSlack timer_slack); 141 }; 142 143 } // namespace base 144 145 #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_ 146