1 // Copyright (c) 2011 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.
5 #include "chrome_frame/task_marshaller.h"
7 #include "base/callback.h"
8 #include "base/logging.h"
10 TaskMarshallerThroughMessageQueue::TaskMarshallerThroughMessageQueue()
15 TaskMarshallerThroughMessageQueue::~TaskMarshallerThroughMessageQueue() {
19 void TaskMarshallerThroughMessageQueue::PostTask(
20 const tracked_objects::Location
& from_here
, const base::Closure
& task
) {
24 bool has_work
= !pending_tasks_
.empty();
25 pending_tasks_
.push(task
);
28 // Don't post message if there is already one.
32 if (!::PostMessage(wnd_
, msg_
, 0, 0)) {
33 DVLOG(1) << "Dropping MSG_EXECUTE_TASK message for destroyed window.";
38 void TaskMarshallerThroughMessageQueue::PostDelayedTask(
39 const tracked_objects::Location
& source
,
40 const base::Closure
& task
,
41 base::TimeDelta
& delay
) {
44 base::AutoLock
lock(lock_
);
45 base::PendingTask
delayed_task(source
, task
, base::TimeTicks::Now() + delay
,
47 base::TimeTicks top_run_time
= delayed_tasks_
.top().delayed_run_time
;
48 delayed_tasks_
.push(delayed_task
);
50 // Reschedule the timer if |delayed_task| will be the next delayed task to
52 if (delayed_task
.delayed_run_time
< top_run_time
) {
53 ::SetTimer(wnd_
, reinterpret_cast<UINT_PTR
>(this),
54 static_cast<DWORD
>(delay
.InMilliseconds()), NULL
);
58 BOOL
TaskMarshallerThroughMessageQueue::ProcessWindowMessage(HWND hWnd
,
64 if (hWnd
== wnd_
&& uMsg
== msg_
) {
70 if (hWnd
== wnd_
&& uMsg
== WM_TIMER
) {
71 ExecuteDelayedTasks();
79 base::Closure
TaskMarshallerThroughMessageQueue::PopTask() {
80 base::AutoLock
lock(lock_
);
81 if (pending_tasks_
.empty())
82 return base::Closure();
84 base::Closure task
= pending_tasks_
.front();
89 void TaskMarshallerThroughMessageQueue::ExecuteQueuedTasks() {
90 DCHECK(CalledOnValidThread());
92 while (!(task
= PopTask()).is_null())
96 void TaskMarshallerThroughMessageQueue::ExecuteDelayedTasks() {
97 DCHECK(CalledOnValidThread());
98 ::KillTimer(wnd_
, reinterpret_cast<UINT_PTR
>(this));
102 if (delayed_tasks_
.empty()) {
107 base::PendingTask next_task
= delayed_tasks_
.top();
108 base::TimeTicks now
= base::TimeTicks::Now();
109 base::TimeTicks next_run
= next_task
.delayed_run_time
;
110 if (next_run
> now
) {
111 int64 delay
= (next_run
- now
).InMillisecondsRoundedUp();
112 ::SetTimer(wnd_
, reinterpret_cast<UINT_PTR
>(this),
113 static_cast<DWORD
>(delay
), NULL
);
118 delayed_tasks_
.pop();
121 // Run the task outside the lock.
122 next_task
.task
.Run();
126 void TaskMarshallerThroughMessageQueue::ClearTasks() {
127 base::AutoLock
lock(lock_
);
128 DVLOG_IF(1, !pending_tasks_
.empty()) << "Destroying "
129 << pending_tasks_
.size()
130 << " pending tasks.";
131 while (!pending_tasks_
.empty())
132 pending_tasks_
.pop();
134 while (!delayed_tasks_
.empty())
135 delayed_tasks_
.pop();