Index: base/message_loop.h |
=================================================================== |
--- base/message_loop.h (revision 1824) |
+++ base/message_loop.h (working copy) |
@@ -80,24 +80,34 @@ |
// DestructionObserver is receiving a notification callback. |
void RemoveDestructionObserver(DestructionObserver* destruction_observer); |
- // Call the task's Run method asynchronously from within a message loop at |
- // some point in the future. With the PostTask variant, tasks are invoked in |
- // FIFO order, inter-mixed with normal UI event processing. With the |
- // PostDelayedTask variant, tasks are called after at least approximately |
- // 'delay_ms' have elapsed. |
+ // The "PostTask" family of methods call the task's Run method asynchronously |
+ // from within a message loop at some point in the future. |
// |
- // The MessageLoop takes ownership of the Task, and deletes it after it |
- // has been Run(). |
+ // With the PostTask variant, tasks are invoked in FIFO order, inter-mixed |
+ // with normal UI or IO event processing. With the PostDelayedTask variant, |
+ // tasks are called after at least approximately 'delay_ms' have elapsed. |
// |
- // NOTE: This method may be called on any thread. The Task will be invoked |
+ // The NonNestable variants work similarly except that they promise never to |
+ // dispatch the task from a nested invocation of MessageLoop::Run. Instead, |
+ // such tasks get deferred until the top-most MessageLoop::Run is executing. |
+ // |
+ // The MessageLoop takes ownership of the Task, and deletes it after it has |
+ // been Run(). |
+ // |
+ // NOTE: These methods may be called on any thread. The Task will be invoked |
// on the thread that executes MessageLoop::Run(). |
+ |
+ void PostTask( |
+ const tracked_objects::Location& from_here, Task* task); |
+ |
+ void PostDelayedTask( |
+ const tracked_objects::Location& from_here, Task* task, int delay_ms); |
- void PostTask(const tracked_objects::Location& from_here, Task* task) { |
- PostDelayedTask(from_here, task, 0); |
- } |
+ void PostNonNestableTask( |
+ const tracked_objects::Location& from_here, Task* task); |
- void PostDelayedTask(const tracked_objects::Location& from_here, Task* task, |
- int delay_ms); |
+ void PostNonNestableDelayedTask( |
+ const tracked_objects::Location& from_here, Task* task, int delay_ms); |
// A variant on PostTask that deletes the given object. This is useful |
// if the object needs to live until the next run of the MessageLoop (for |
@@ -110,7 +120,7 @@ |
// from RefCountedThreadSafe<T>! |
template <class T> |
void DeleteSoon(const tracked_objects::Location& from_here, T* object) { |
- PostTask(from_here, new DeleteTask<T>(object)); |
+ PostNonNestableTask(from_here, new DeleteTask<T>(object)); |
} |
// A variant on PostTask that releases the given reference counted object |
@@ -125,7 +135,7 @@ |
// RefCountedThreadSafe<T>! |
template <class T> |
void ReleaseSoon(const tracked_objects::Location& from_here, T* object) { |
- PostTask(from_here, new ReleaseTask<T>(object)); |
+ PostNonNestableTask(from_here, new ReleaseTask<T>(object)); |
} |
// Run the message loop. |
@@ -199,10 +209,6 @@ |
return loop; |
} |
- // Returns the TimerManager object for the current thread. This getter is |
- // deprecated. Please use OneShotTimer or RepeatingTimer instead. |
- base::TimerManager* timer_manager_deprecated() { return &timer_manager_; } |
- |
// Enables or disables the recursive task processing. This happens in the case |
// of recursive message loops. Some unwanted message loop may occurs when |
// using common controls or printer functions. By default, recursive task |
@@ -229,11 +235,8 @@ |
exception_restoration_ = restore; |
} |
- |
//---------------------------------------------------------------------------- |
protected: |
- friend class base::TimerManager; // So it can call DidChangeNextTimerExpiry |
- |
struct RunState { |
// Used to count how many Run() invocations are on the stack. |
int run_depth; |
@@ -256,71 +259,24 @@ |
RunState* previous_state_; |
}; |
- // A prioritized queue with interface that mostly matches std::queue<>. |
- // For debugging/performance testing, you can swap in std::queue<Task*>. |
- class PrioritizedTaskQueue { |
- public: |
- PrioritizedTaskQueue() : next_sequence_number_(0) {} |
- ~PrioritizedTaskQueue() {} |
- void pop() { queue_.pop(); } |
- bool empty() { return queue_.empty(); } |
- size_t size() { return queue_.size(); } |
- Task* front() { return queue_.top().task(); } |
- void push(Task * task); |
+ // This structure is copied around by value. |
+ struct PendingTask { |
+ Task* task; // The task to run. |
+ Time delayed_run_time; // The time when the task should be run. |
+ int sequence_num; // Used to facilitate sorting by run time. |
+ bool nestable; // True if OK to dispatch from a nested loop. |
- private: |
- class PrioritizedTask { |
- public: |
- PrioritizedTask(Task* task, int sequence_number) |
- : task_(task), |
- sequence_number_(sequence_number), |
- priority_(task->priority()) {} |
- Task* task() const { return task_; } |
- bool operator < (PrioritizedTask const & right) const ; |
- |
- private: |
- Task* task_; |
- // Number to ensure (default) FIFO ordering in a PriorityQueue. |
- int sequence_number_; |
- // Priority of task when pushed. |
- int priority_; |
- }; // class PrioritizedTask |
- |
- std::priority_queue<PrioritizedTask> queue_; |
- // Default sequence number used when push'ing (monotonically decreasing). |
- int next_sequence_number_; |
- DISALLOW_EVIL_CONSTRUCTORS(PrioritizedTaskQueue); |
+ PendingTask(Task* task, bool nestable) |
+ : task(task), sequence_num(0), nestable(nestable) { |
+ } |
+ |
+ // Used to support sorting. |
+ bool operator<(const PendingTask& other) const; |
}; |
- // Implementation of a TaskQueue as a null terminated list, with end pointers. |
- class TaskQueue { |
- public: |
- TaskQueue() : first_(NULL), last_(NULL) {} |
- void Push(Task* task); |
- Task* Pop(); // Extract the next Task from the queue, and return it. |
- bool Empty() const { return !first_; } |
- private: |
- Task* first_; |
- Task* last_; |
- }; |
+ typedef std::queue<PendingTask> TaskQueue; |
+ typedef std::priority_queue<PendingTask> DelayedTaskQueue; |
- // Implementation of a Task queue that automatically switches into a priority |
- // queue if it observes any non-zero priorities in tasks. |
- class OptionallyPrioritizedTaskQueue { |
- public: |
- OptionallyPrioritizedTaskQueue() : use_priority_queue_(false) {} |
- void Push(Task* task); |
- Task* Pop(); // Extract next Task from queue, and return it. |
- bool Empty(); |
- bool use_priority_queue() const { return use_priority_queue_; } |
- |
- private: |
- bool use_priority_queue_; |
- PrioritizedTaskQueue prioritized_queue_; |
- TaskQueue queue_; |
- DISALLOW_EVIL_CONSTRUCTORS(OptionallyPrioritizedTaskQueue); |
- }; |
- |
#if defined(OS_WIN) |
base::MessagePumpWin* pump_win() { |
return static_cast<base::MessagePumpWin*>(pump_.get()); |
@@ -356,10 +312,9 @@ |
// Runs the specified task and deletes it. |
void RunTask(Task* task); |
- // Make state adjustments just before and after running tasks so that we can |
- // continue to work if a native message loop is employed during a task. |
- void BeforeTaskRunSetup(); |
- void AfterTaskRunRestore(); |
+ // Calls RunTask or queues the pending_task on the deferred task list if it |
+ // cannot be run right now. Returns true if the task was run. |
+ bool DeferOrRunPendingTask(const PendingTask& pending_task); |
// Load tasks from the incoming_queue_ into work_queue_ if the latter is |
// empty. The former requires a lock to access, while the latter is directly |
@@ -371,21 +326,9 @@ |
void DeletePendingTasks(); |
// Post a task to our incomming queue. |
- void PostTaskInternal(Task* task); |
+ void PostTask_Helper(const tracked_objects::Location& from_here, Task* task, |
+ int delay_ms, bool nestable); |
- // Called by the TimerManager when its next timer changes. |
- void DidChangeNextTimerExpiry(); |
- |
- // Entry point for TimerManager to request the Run() of a task. If we |
- // created the task during an PostTask(FROM_HERE, ), then we will also |
- // perform destructions, and we'll have the option of queueing the task. If |
- // we didn't create the timer, then we will Run it immediately. |
- bool RunTimerTask(Timer* timer); |
- |
- // Since some Timer's are owned by MessageLoop, the TimerManager (when it is |
- // being destructed) passses us the timers to discard (without doing a Run()). |
- void DiscardTimer(Timer* timer); |
- |
// base::MessagePump::Delegate methods: |
virtual bool DoWork(); |
virtual bool DoDelayedWork(Time* next_delayed_work_time); |
@@ -406,16 +349,17 @@ |
Type type_; |
- base::TimerManager timer_manager_; |
+ // A list of tasks that need to be processed by this instance. Note that |
+ // this queue is only accessed (push/pop) by our current thread. |
+ TaskQueue work_queue_; |
+ |
+ // Contains delayed tasks, sorted by their 'delayed_run_time' property. |
+ DelayedTaskQueue delayed_work_queue_; |
- // A list of tasks that need to be processed by this instance. Note that this |
- // queue is only accessed (push/pop) by our current thread. |
- // As an optimization, when we don't need to use the prioritization of |
- // work_queue_, we use a null terminated list (TaskQueue) as our |
- // implementation of the queue. This saves on memory (list uses pointers |
- // internal to Task) and probably runs faster than the priority queue when |
- // there was no real prioritization. |
- OptionallyPrioritizedTaskQueue work_queue_; |
+ // A queue of non-nestable tasks that we had to defer because when it came |
+ // time to execute them we were in a nested message loop. They will execute |
+ // once we're out of nested message loops. |
+ TaskQueue deferred_non_nestable_work_queue_; |
scoped_refptr<base::MessagePump> pump_; |
@@ -438,13 +382,11 @@ |
// Protect access to incoming_queue_. |
Lock incoming_queue_lock_; |
- // A null terminated list of non-nestable tasks that we had to delay because |
- // when it came time to execute them we were in a nested message loop. They |
- // will execute once we're out of nested message loops. |
- TaskQueue delayed_non_nestable_queue_; |
- |
RunState* state_; |
+ // The next sequence number to use for delayed tasks. |
+ int next_sequence_num_; |
+ |
DISALLOW_COPY_AND_ASSIGN(MessageLoop); |
}; |