OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome_frame/task_marshaller.h" | |
6 | |
7 #include "base/callback.h" | |
8 #include "base/logging.h" | |
9 | |
10 TaskMarshallerThroughMessageQueue::TaskMarshallerThroughMessageQueue() | |
11 : wnd_(NULL), | |
12 msg_(0xFFFF) { | |
13 } | |
14 | |
15 TaskMarshallerThroughMessageQueue::~TaskMarshallerThroughMessageQueue() { | |
16 ClearTasks(); | |
17 } | |
18 | |
19 void TaskMarshallerThroughMessageQueue::PostTask( | |
20 const tracked_objects::Location& from_here, const base::Closure& task) { | |
21 DCHECK(wnd_ != NULL); | |
22 | |
23 lock_.Acquire(); | |
24 bool has_work = !pending_tasks_.empty(); | |
25 pending_tasks_.push(task); | |
26 lock_.Release(); | |
27 | |
28 // Don't post message if there is already one. | |
29 if (has_work) | |
30 return; | |
31 | |
32 if (!::PostMessage(wnd_, msg_, 0, 0)) { | |
33 DVLOG(1) << "Dropping MSG_EXECUTE_TASK message for destroyed window."; | |
34 ClearTasks(); | |
35 } | |
36 } | |
37 | |
38 void TaskMarshallerThroughMessageQueue::PostDelayedTask( | |
39 const tracked_objects::Location& source, | |
40 const base::Closure& task, | |
41 base::TimeDelta& delay) { | |
42 DCHECK(wnd_); | |
43 | |
44 base::AutoLock lock(lock_); | |
45 base::PendingTask delayed_task(source, task, base::TimeTicks::Now() + delay, | |
46 true); | |
47 base::TimeTicks top_run_time = delayed_tasks_.top().delayed_run_time; | |
48 delayed_tasks_.push(delayed_task); | |
49 | |
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) { | |
53 ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this), | |
54 static_cast<DWORD>(delay.InMilliseconds()), NULL); | |
55 } | |
56 } | |
57 | |
58 BOOL TaskMarshallerThroughMessageQueue::ProcessWindowMessage(HWND hWnd, | |
59 UINT uMsg, | |
60 WPARAM wParam, | |
61 LPARAM lParam, | |
62 LRESULT& lResult, | |
63 DWORD dwMsgMapID) { | |
64 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; | |
77 } | |
78 | |
79 base::Closure TaskMarshallerThroughMessageQueue::PopTask() { | |
80 base::AutoLock lock(lock_); | |
81 if (pending_tasks_.empty()) | |
82 return base::Closure(); | |
83 | |
84 base::Closure task = pending_tasks_.front(); | |
85 pending_tasks_.pop(); | |
86 return task; | |
87 } | |
88 | |
89 void TaskMarshallerThroughMessageQueue::ExecuteQueuedTasks() { | |
90 DCHECK(CalledOnValidThread()); | |
91 base::Closure task; | |
92 while (!(task = PopTask()).is_null()) | |
93 task.Run(); | |
94 } | |
95 | |
96 void TaskMarshallerThroughMessageQueue::ExecuteDelayedTasks() { | |
97 DCHECK(CalledOnValidThread()); | |
98 ::KillTimer(wnd_, reinterpret_cast<UINT_PTR>(this)); | |
99 while (true) { | |
100 lock_.Acquire(); | |
101 | |
102 if (delayed_tasks_.empty()) { | |
103 lock_.Release(); | |
104 return; | |
105 } | |
106 | |
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); | |
114 lock_.Release(); | |
115 return; | |
116 } | |
117 | |
118 delayed_tasks_.pop(); | |
119 lock_.Release(); | |
120 | |
121 // Run the task outside the lock. | |
122 next_task.task.Run(); | |
123 } | |
124 } | |
125 | |
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(); | |
133 | |
134 while (!delayed_tasks_.empty()) | |
135 delayed_tasks_.pop(); | |
136 } | |
OLD | NEW |