blob: c02c245faf60cc77d5b6b626cbb5cf26f5679ab5 [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"
[email protected]c6944272012-01-06 22:12:286
7#include "base/callback.h"
8#include "base/logging.h"
[email protected]5a8db802010-10-06 17:34:439
[email protected]262060ff2011-11-17 23:26:5310TaskMarshallerThroughMessageQueue::TaskMarshallerThroughMessageQueue()
11 : wnd_(NULL),
12 msg_(0xFFFF) {
[email protected]5a8db802010-10-06 17:34:4313}
14
15TaskMarshallerThroughMessageQueue::~TaskMarshallerThroughMessageQueue() {
[email protected]262060ff2011-11-17 23:26:5316 ClearTasks();
[email protected]5a8db802010-10-06 17:34:4317}
18
19void TaskMarshallerThroughMessageQueue::PostTask(
[email protected]262060ff2011-11-17 23:26:5320 const tracked_objects::Location& from_here, const base::Closure& task) {
[email protected]11b6e602010-10-13 16:02:2621 DCHECK(wnd_ != NULL);
[email protected]bb04c4e2011-11-18 20:44:2222
[email protected]11b6e602010-10-13 16:02:2623 lock_.Acquire();
24 bool has_work = !pending_tasks_.empty();
25 pending_tasks_.push(task);
26 lock_.Release();
[email protected]5a8db802010-10-06 17:34:4327
[email protected]11b6e602010-10-13 16:02:2628 // Don't post message if there is already one.
29 if (has_work)
30 return;
[email protected]5a8db802010-10-06 17:34:4331
[email protected]11b6e602010-10-13 16:02:2632 if (!::PostMessage(wnd_, msg_, 0, 0)) {
[email protected]2b9a9f162010-10-19 20:30:4533 DVLOG(1) << "Dropping MSG_EXECUTE_TASK message for destroyed window.";
[email protected]262060ff2011-11-17 23:26:5334 ClearTasks();
[email protected]11b6e602010-10-13 16:02:2635 }
[email protected]5a8db802010-10-06 17:34:4336}
37
38void TaskMarshallerThroughMessageQueue::PostDelayedTask(
[email protected]2b9a9f162010-10-19 20:30:4539 const tracked_objects::Location& source,
[email protected]262060ff2011-11-17 23:26:5340 const base::Closure& task,
[email protected]11b6e602010-10-13 16:02:2641 base::TimeDelta& delay) {
[email protected]262060ff2011-11-17 23:26:5342 DCHECK(wnd_);
43
[email protected]20305ec2011-01-21 04:55:5244 base::AutoLock lock(lock_);
[email protected]262060ff2011-11-17 23:26:5345 base::PendingTask delayed_task(source, task, base::TimeTicks::Now() + delay,
46 true);
47 base::TimeTicks top_run_time = delayed_tasks_.top().delayed_run_time;
[email protected]11b6e602010-10-13 16:02:2648 delayed_tasks_.push(delayed_task);
[email protected]262060ff2011-11-17 23:26:5349
50 // Reschedule the timer if |delayed_task| will be the next delayed task to
51 // run.
52 if (delayed_task.delayed_run_time < top_run_time) {
[email protected]11b6e602010-10-13 16:02:2653 ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this),
[email protected]262060ff2011-11-17 23:26:5354 static_cast<DWORD>(delay.InMilliseconds()), NULL);
[email protected]11b6e602010-10-13 16:02:2655 }
56}
57
58BOOL TaskMarshallerThroughMessageQueue::ProcessWindowMessage(HWND hWnd,
[email protected]2b9a9f162010-10-19 20:30:4559 UINT uMsg,
60 WPARAM wParam,
61 LPARAM lParam,
62 LRESULT& lResult,
63 DWORD dwMsgMapID) {
[email protected]11b6e602010-10-13 16:02:2664 if (hWnd == wnd_ && uMsg == msg_) {
65 ExecuteQueuedTasks();
66 lResult = 0;
67 return TRUE;
68 }
69
70 if (hWnd == wnd_ && uMsg == WM_TIMER) {
71 ExecuteDelayedTasks();
72 lResult = 0;
73 return TRUE;
74 }
75
76 return FALSE;
[email protected]5a8db802010-10-06 17:34:4377}
78
[email protected]262060ff2011-11-17 23:26:5379base::Closure TaskMarshallerThroughMessageQueue::PopTask() {
[email protected]20305ec2011-01-21 04:55:5280 base::AutoLock lock(lock_);
[email protected]262060ff2011-11-17 23:26:5381 if (pending_tasks_.empty())
82 return base::Closure();
83
84 base::Closure task = pending_tasks_.front();
85 pending_tasks_.pop();
[email protected]5a8db802010-10-06 17:34:4386 return task;
87}
88
89void TaskMarshallerThroughMessageQueue::ExecuteQueuedTasks() {
90 DCHECK(CalledOnValidThread());
[email protected]262060ff2011-11-17 23:26:5391 base::Closure task;
92 while (!(task = PopTask()).is_null())
93 task.Run();
[email protected]5a8db802010-10-06 17:34:4394}
95
96void TaskMarshallerThroughMessageQueue::ExecuteDelayedTasks() {
97 DCHECK(CalledOnValidThread());
98 ::KillTimer(wnd_, reinterpret_cast<UINT_PTR>(this));
[email protected]262060ff2011-11-17 23:26:5399 while (true) {
[email protected]5a8db802010-10-06 17:34:43100 lock_.Acquire();
101
102 if (delayed_tasks_.empty()) {
103 lock_.Release();
104 return;
105 }
106
[email protected]262060ff2011-11-17 23:26:53107 base::PendingTask next_task = delayed_tasks_.top();
108 base::TimeTicks now = base::TimeTicks::Now();
109 base::TimeTicks next_run = next_task.delayed_run_time;
[email protected]5a8db802010-10-06 17:34:43110 if (next_run > now) {
111 int64 delay = (next_run - now).InMillisecondsRoundedUp();
112 ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this),
[email protected]262060ff2011-11-17 23:26:53113 static_cast<DWORD>(delay), NULL);
[email protected]5a8db802010-10-06 17:34:43114 lock_.Release();
115 return;
116 }
117
118 delayed_tasks_.pop();
119 lock_.Release();
120
121 // Run the task outside the lock.
[email protected]262060ff2011-11-17 23:26:53122 next_task.task.Run();
[email protected]5a8db802010-10-06 17:34:43123 }
124}
125
[email protected]262060ff2011-11-17 23:26:53126void TaskMarshallerThroughMessageQueue::ClearTasks() {
[email protected]20305ec2011-01-21 04:55:52127 base::AutoLock lock(lock_);
[email protected]5044da82010-10-27 01:09:16128 DVLOG_IF(1, !pending_tasks_.empty()) << "Destroying "
129 << pending_tasks_.size()
130 << " pending tasks.";
[email protected]262060ff2011-11-17 23:26:53131 while (!pending_tasks_.empty())
[email protected]5a8db802010-10-06 17:34:43132 pending_tasks_.pop();
[email protected]5a8db802010-10-06 17:34:43133
[email protected]262060ff2011-11-17 23:26:53134 while (!delayed_tasks_.empty())
[email protected]5a8db802010-10-06 17:34:43135 delayed_tasks_.pop();
[email protected]5a8db802010-10-06 17:34:43136}