diff options
author | stoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-06 17:34:43 +0000 |
---|---|---|
committer | stoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-06 17:34:43 +0000 |
commit | 5a8db8040f8f1e4e320f882b1ffea89b6f32d5ea (patch) | |
tree | b29c31cc55b6fec96d9b34e543d9425fce26153d /chrome_frame/task_marshaller.cc | |
parent | 85fb807c92bcf07512d12bff47dd5a9e22c03161 (diff) | |
download | chromium_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.cc | 132 |
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; +} |