Updating trunk VERSION from 993.0 to 994.0
[chromium-blink-merge.git] / chrome_frame / task_marshaller.cc
blob5bc6a12d4a6d450dd49a867472aec13fe3fa3743
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"
6 #include "base/task.h"
8 TaskMarshallerThroughMessageQueue::TaskMarshallerThroughMessageQueue()
9 : wnd_(NULL),
10 msg_(0xFFFF) {
13 TaskMarshallerThroughMessageQueue::~TaskMarshallerThroughMessageQueue() {
14 ClearTasks();
17 void TaskMarshallerThroughMessageQueue::PostTask(
18 const tracked_objects::Location& from_here, const base::Closure& task) {
19 DCHECK(wnd_ != NULL);
21 lock_.Acquire();
22 bool has_work = !pending_tasks_.empty();
23 pending_tasks_.push(task);
24 lock_.Release();
26 // Don't post message if there is already one.
27 if (has_work)
28 return;
30 if (!::PostMessage(wnd_, msg_, 0, 0)) {
31 DVLOG(1) << "Dropping MSG_EXECUTE_TASK message for destroyed window.";
32 ClearTasks();
36 void TaskMarshallerThroughMessageQueue::PostDelayedTask(
37 const tracked_objects::Location& source,
38 const base::Closure& task,
39 base::TimeDelta& delay) {
40 DCHECK(wnd_);
42 base::AutoLock lock(lock_);
43 base::PendingTask delayed_task(source, task, base::TimeTicks::Now() + delay,
44 true);
45 base::TimeTicks top_run_time = delayed_tasks_.top().delayed_run_time;
46 delayed_tasks_.push(delayed_task);
48 // Reschedule the timer if |delayed_task| will be the next delayed task to
49 // run.
50 if (delayed_task.delayed_run_time < top_run_time) {
51 ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this),
52 static_cast<DWORD>(delay.InMilliseconds()), NULL);
56 BOOL TaskMarshallerThroughMessageQueue::ProcessWindowMessage(HWND hWnd,
57 UINT uMsg,
58 WPARAM wParam,
59 LPARAM lParam,
60 LRESULT& lResult,
61 DWORD dwMsgMapID) {
62 if (hWnd == wnd_ && uMsg == msg_) {
63 ExecuteQueuedTasks();
64 lResult = 0;
65 return TRUE;
68 if (hWnd == wnd_ && uMsg == WM_TIMER) {
69 ExecuteDelayedTasks();
70 lResult = 0;
71 return TRUE;
74 return FALSE;
77 base::Closure TaskMarshallerThroughMessageQueue::PopTask() {
78 base::AutoLock lock(lock_);
79 if (pending_tasks_.empty())
80 return base::Closure();
82 base::Closure task = pending_tasks_.front();
83 pending_tasks_.pop();
84 return task;
87 void TaskMarshallerThroughMessageQueue::ExecuteQueuedTasks() {
88 DCHECK(CalledOnValidThread());
89 base::Closure task;
90 while (!(task = PopTask()).is_null())
91 task.Run();
94 void TaskMarshallerThroughMessageQueue::ExecuteDelayedTasks() {
95 DCHECK(CalledOnValidThread());
96 ::KillTimer(wnd_, reinterpret_cast<UINT_PTR>(this));
97 while (true) {
98 lock_.Acquire();
100 if (delayed_tasks_.empty()) {
101 lock_.Release();
102 return;
105 base::PendingTask next_task = delayed_tasks_.top();
106 base::TimeTicks now = base::TimeTicks::Now();
107 base::TimeTicks next_run = next_task.delayed_run_time;
108 if (next_run > now) {
109 int64 delay = (next_run - now).InMillisecondsRoundedUp();
110 ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this),
111 static_cast<DWORD>(delay), NULL);
112 lock_.Release();
113 return;
116 delayed_tasks_.pop();
117 lock_.Release();
119 // Run the task outside the lock.
120 next_task.task.Run();
124 void TaskMarshallerThroughMessageQueue::ClearTasks() {
125 base::AutoLock lock(lock_);
126 DVLOG_IF(1, !pending_tasks_.empty()) << "Destroying "
127 << pending_tasks_.size()
128 << " pending tasks.";
129 while (!pending_tasks_.empty())
130 pending_tasks_.pop();
132 while (!delayed_tasks_.empty())
133 delayed_tasks_.pop();