summaryrefslogtreecommitdiffstats
path: root/chrome_frame/task_marshaller.cc
diff options
context:
space:
mode:
authorstoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-06 17:34:43 +0000
committerstoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-06 17:34:43 +0000
commit5a8db8040f8f1e4e320f882b1ffea89b6f32d5ea (patch)
treeb29c31cc55b6fec96d9b34e543d9425fce26153d /chrome_frame/task_marshaller.cc
parent85fb807c92bcf07512d12bff47dd5a9e22c03161 (diff)
downloadchromium_src-5a8db8040f8f1e4e320f882b1ffea89b6f32d5ea.zip
chromium_src-5a8db8040f8f1e4e320f882b1ffea89b6f32d5ea.tar.gz
chromium_src-5a8db8040f8f1e4e320f882b1ffea89b6f32d5ea.tar.bz2
Reland http://codereview.chromium.org/3528004/
Initial skeleton for refactored ChromeFrameAutomationClient and AutomationProxy for the needs of ChromeFrame. TBR=amit Review URL: http://codereview.chromium.org/3567019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61665 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/task_marshaller.cc')
-rw-r--r--chrome_frame/task_marshaller.cc132
1 files changed, 132 insertions, 0 deletions
diff --git a/chrome_frame/task_marshaller.cc b/chrome_frame/task_marshaller.cc
new file mode 100644
index 0000000..ba1df2c
--- /dev/null
+++ b/chrome_frame/task_marshaller.cc
@@ -0,0 +1,132 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "chrome_frame/task_marshaller.h"
+#include "base/task.h"
+
+TaskMarshallerThroughMessageQueue::TaskMarshallerThroughMessageQueue() {
+ wnd_ = NULL;
+ msg_ = 0xFFFF;
+}
+
+TaskMarshallerThroughMessageQueue::~TaskMarshallerThroughMessageQueue() {
+ DeleteAll();
+}
+
+void TaskMarshallerThroughMessageQueue::PostTask(
+ const tracked_objects::Location& from_here, Task* task) {
+ task->SetBirthPlace(from_here);
+ lock_.Acquire();
+ bool has_work = !pending_tasks_.empty();
+ pending_tasks_.push(task);
+ lock_.Release();
+
+ // Don't post message if there is already one.
+ if (has_work)
+ return;
+
+ if (!::PostMessage(wnd_, msg_, 0, 0)) {
+ DLOG(INFO) << "Dropping MSG_EXECUTE_TASK message for destroyed window.";
+ DeleteAll();
+ }
+}
+
+void TaskMarshallerThroughMessageQueue::PostDelayedTask(
+ const tracked_objects::Location& source, Task* task,
+ base::TimeDelta& delay) {
+ AutoLock lock(lock_);
+ DelayedTask delayed_task(task, base::Time::Now() + delay);
+ delayed_tasks_.push(delayed_task);
+ // If we become the 'top' task - reschedule the timer.
+ if (delayed_tasks_.top().task == task) {
+ ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this),
+ static_cast<DWORD>(delay.InMilliseconds()), NULL);
+ }
+}
+
+Task* TaskMarshallerThroughMessageQueue::PopTask() {
+ AutoLock lock(lock_);
+ Task* task = NULL;
+ if (!pending_tasks_.empty()) {
+ task = pending_tasks_.front();
+ pending_tasks_.pop();
+ }
+ return task;
+}
+
+void TaskMarshallerThroughMessageQueue::ExecuteQueuedTasks() {
+ DCHECK(CalledOnValidThread());
+ Task* task;
+ while ((task = PopTask()) != NULL) {
+ RunTask(task);
+ }
+}
+
+void TaskMarshallerThroughMessageQueue::ExecuteDelayedTasks() {
+ DCHECK(CalledOnValidThread());
+ ::KillTimer(wnd_, reinterpret_cast<UINT_PTR>(this));
+ while (1) {
+ lock_.Acquire();
+
+ if (delayed_tasks_.empty()) {
+ lock_.Release();
+ return;
+ }
+
+ base::Time now = base::Time::Now();
+ DelayedTask next_task = delayed_tasks_.top();
+ base::Time next_run = next_task.run_at;
+ if (next_run > now) {
+ int64 delay = (next_run - now).InMillisecondsRoundedUp();
+ ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this),
+ static_cast<DWORD>(delay), NULL);
+ lock_.Release();
+ return;
+ }
+
+ delayed_tasks_.pop();
+ lock_.Release();
+
+ // Run the task outside the lock.
+ RunTask(next_task.task);
+ }
+}
+
+void TaskMarshallerThroughMessageQueue::DeleteAll() {
+ AutoLock lock(lock_);
+ DLOG_IF(INFO, !pending_tasks_.empty()) <<
+ "Destroying " << pending_tasks_.size() << " pending tasks.";
+ while (!pending_tasks_.empty()) {
+ Task* task = pending_tasks_.front();
+ pending_tasks_.pop();
+ delete task;
+ }
+
+ while (!delayed_tasks_.empty()) {
+ delete delayed_tasks_.top().task;
+ delayed_tasks_.pop();
+ }
+}
+
+void TaskMarshallerThroughMessageQueue::RunTask(Task* task) {
+ ++invoke_task_;
+ task->Run();
+ --invoke_task_;
+ delete task;
+}
+
+bool TaskMarshallerThroughMessageQueue::DelayedTask::operator<(
+ const DelayedTask& other) const {
+ // Since the top of a priority queue is defined as the "greatest" element, we
+ // need to invert the comparison here. We want the smaller time to be at the
+ // top of the heap.
+ if (run_at < other.run_at)
+ return false;
+
+ if (run_at > other.run_at)
+ return true;
+
+ // If the times happen to match, then we use the sequence number to decide.
+ // Compare the difference to support integer roll-over.
+ return (seq - other.seq) > 0;
+}