blob: 9ad74a0ab5615c710f804a357579643d9da1b606 [file] [log] [blame]
[email protected]c62dd9d2011-09-21 18:05:411// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]5a8db802010-10-06 17:34:432// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
[email protected]2b9a9f162010-10-19 20:30:454
[email protected]5a8db802010-10-06 17:34:435#include "chrome_frame/task_marshaller.h"
6#include "base/task.h"
7
[email protected]262060ff2011-11-17 23:26:538TaskMarshallerThroughMessageQueue::TaskMarshallerThroughMessageQueue()
9 : wnd_(NULL),
10 msg_(0xFFFF) {
[email protected]5a8db802010-10-06 17:34:4311}
12
13TaskMarshallerThroughMessageQueue::~TaskMarshallerThroughMessageQueue() {
[email protected]262060ff2011-11-17 23:26:5314 ClearTasks();
[email protected]5a8db802010-10-06 17:34:4315}
16
17void TaskMarshallerThroughMessageQueue::PostTask(
[email protected]262060ff2011-11-17 23:26:5318 const tracked_objects::Location& from_here, const base::Closure& task) {
[email protected]11b6e602010-10-13 16:02:2619 DCHECK(wnd_ != NULL);
[email protected]11b6e602010-10-13 16:02:2620 lock_.Acquire();
21 bool has_work = !pending_tasks_.empty();
22 pending_tasks_.push(task);
23 lock_.Release();
[email protected]5a8db802010-10-06 17:34:4324
[email protected]11b6e602010-10-13 16:02:2625 // Don't post message if there is already one.
26 if (has_work)
27 return;
[email protected]5a8db802010-10-06 17:34:4328
[email protected]11b6e602010-10-13 16:02:2629 if (!::PostMessage(wnd_, msg_, 0, 0)) {
[email protected]2b9a9f162010-10-19 20:30:4530 DVLOG(1) << "Dropping MSG_EXECUTE_TASK message for destroyed window.";
[email protected]262060ff2011-11-17 23:26:5331 ClearTasks();
[email protected]11b6e602010-10-13 16:02:2632 }
[email protected]5a8db802010-10-06 17:34:4333}
34
35void TaskMarshallerThroughMessageQueue::PostDelayedTask(
[email protected]2b9a9f162010-10-19 20:30:4536 const tracked_objects::Location& source,
[email protected]262060ff2011-11-17 23:26:5337 const base::Closure& task,
[email protected]11b6e602010-10-13 16:02:2638 base::TimeDelta& delay) {
[email protected]262060ff2011-11-17 23:26:5339 DCHECK(wnd_);
40
[email protected]20305ec2011-01-21 04:55:5241 base::AutoLock lock(lock_);
[email protected]262060ff2011-11-17 23:26:5342 base::PendingTask delayed_task(source, task, base::TimeTicks::Now() + delay,
43 true);
44 base::TimeTicks top_run_time = delayed_tasks_.top().delayed_run_time;
[email protected]11b6e602010-10-13 16:02:2645 delayed_tasks_.push(delayed_task);
[email protected]262060ff2011-11-17 23:26:5346
47 // Reschedule the timer if |delayed_task| will be the next delayed task to
48 // run.
49 if (delayed_task.delayed_run_time < top_run_time) {
[email protected]11b6e602010-10-13 16:02:2650 ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this),
[email protected]262060ff2011-11-17 23:26:5351 static_cast<DWORD>(delay.InMilliseconds()), NULL);
[email protected]11b6e602010-10-13 16:02:2652 }
53}
54
55BOOL TaskMarshallerThroughMessageQueue::ProcessWindowMessage(HWND hWnd,
[email protected]2b9a9f162010-10-19 20:30:4556 UINT uMsg,
57 WPARAM wParam,
58 LPARAM lParam,
59 LRESULT& lResult,
60 DWORD dwMsgMapID) {
[email protected]11b6e602010-10-13 16:02:2661 if (hWnd == wnd_ && uMsg == msg_) {
62 ExecuteQueuedTasks();
63 lResult = 0;
64 return TRUE;
65 }
66
67 if (hWnd == wnd_ && uMsg == WM_TIMER) {
68 ExecuteDelayedTasks();
69 lResult = 0;
70 return TRUE;
71 }
72
73 return FALSE;
[email protected]5a8db802010-10-06 17:34:4374}
75
[email protected]262060ff2011-11-17 23:26:5376base::Closure TaskMarshallerThroughMessageQueue::PopTask() {
[email protected]20305ec2011-01-21 04:55:5277 base::AutoLock lock(lock_);
[email protected]262060ff2011-11-17 23:26:5378 if (pending_tasks_.empty())
79 return base::Closure();
80
81 base::Closure task = pending_tasks_.front();
82 pending_tasks_.pop();
[email protected]5a8db802010-10-06 17:34:4383 return task;
84}
85
86void TaskMarshallerThroughMessageQueue::ExecuteQueuedTasks() {
87 DCHECK(CalledOnValidThread());
[email protected]262060ff2011-11-17 23:26:5388 base::Closure task;
89 while (!(task = PopTask()).is_null())
90 task.Run();
[email protected]5a8db802010-10-06 17:34:4391}
92
93void TaskMarshallerThroughMessageQueue::ExecuteDelayedTasks() {
94 DCHECK(CalledOnValidThread());
95 ::KillTimer(wnd_, reinterpret_cast<UINT_PTR>(this));
[email protected]262060ff2011-11-17 23:26:5396 while (true) {
[email protected]5a8db802010-10-06 17:34:4397 lock_.Acquire();
98
99 if (delayed_tasks_.empty()) {
100 lock_.Release();
101 return;
102 }
103
[email protected]262060ff2011-11-17 23:26:53104 base::PendingTask next_task = delayed_tasks_.top();
105 base::TimeTicks now = base::TimeTicks::Now();
106 base::TimeTicks next_run = next_task.delayed_run_time;
[email protected]5a8db802010-10-06 17:34:43107 if (next_run > now) {
108 int64 delay = (next_run - now).InMillisecondsRoundedUp();
109 ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this),
[email protected]262060ff2011-11-17 23:26:53110 static_cast<DWORD>(delay), NULL);
[email protected]5a8db802010-10-06 17:34:43111 lock_.Release();
112 return;
113 }
114
115 delayed_tasks_.pop();
116 lock_.Release();
117
118 // Run the task outside the lock.
[email protected]262060ff2011-11-17 23:26:53119 next_task.task.Run();
[email protected]5a8db802010-10-06 17:34:43120 }
121}
122
[email protected]262060ff2011-11-17 23:26:53123void TaskMarshallerThroughMessageQueue::ClearTasks() {
[email protected]20305ec2011-01-21 04:55:52124 base::AutoLock lock(lock_);
[email protected]5044da82010-10-27 01:09:16125 DVLOG_IF(1, !pending_tasks_.empty()) << "Destroying "
126 << pending_tasks_.size()
127 << " pending tasks.";
[email protected]262060ff2011-11-17 23:26:53128 while (!pending_tasks_.empty())
[email protected]5a8db802010-10-06 17:34:43129 pending_tasks_.pop();
[email protected]5a8db802010-10-06 17:34:43130
[email protected]262060ff2011-11-17 23:26:53131 while (!delayed_tasks_.empty())
[email protected]5a8db802010-10-06 17:34:43132 delayed_tasks_.pop();
[email protected]5a8db802010-10-06 17:34:43133}