15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/plugin_thread_task_runner.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::TimeDelta CalcTimeDelta(base::TimeTicks when) {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::max(when - base::TimeTicks::Now(), base::TimeDelta());
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginThreadTaskRunner::Delegate::~Delegate() {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginThreadTaskRunner::PluginThreadTaskRunner(Delegate* delegate)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : plugin_thread_id_(base::PlatformThread::CurrentId()),
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_(false, false),
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_(delegate),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_sequence_num_(0),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      quit_received_(false),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stopped_(false) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginThreadTaskRunner::~PluginThreadTaskRunner() {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(delegate_ == NULL);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(stopped_);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginThreadTaskRunner::DetachAndRunShutdownLoop() {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BelongsToCurrentThread());
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Detach from the plugin thread and redirect all tasks posted after this
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // point to the shutdown task loop.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(delegate_ != NULL);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!stopped_);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_ = NULL;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stopped_ = quit_received_;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When DetachAndRunShutdownLoop() is called from NPP_Destroy() all scheduled
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // timers are cancelled. It is OK to clear |scheduled_timers_| even if
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the timers weren't actually cancelled (i.e. DetachAndRunShutdownLoop() is
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // called before NPP_Destroy()).
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduled_timers_.clear();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run all tasks that are due.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessIncomingTasks();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunDueTasks(base::TimeTicks::Now());
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!stopped_) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delayed_queue_.empty()) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_.Wait();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_.TimedWait(CalcTimeDelta(delayed_queue_.top().delayed_run_time));
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Run all tasks that are due.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessIncomingTasks();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunDueTasks(base::TimeTicks::Now());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stopped_ = quit_received_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginThreadTaskRunner::Quit() {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!quit_received_) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_received_ = true;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_.Signal();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginThreadTaskRunner::PostDelayedTask(
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& task,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta delay) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wrap the task into |base::PendingTask|.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks delayed_run_time;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delay > base::TimeDelta()) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delayed_run_time = base::TimeTicks::Now() + delay;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(delay.InMilliseconds(), 0) << "delay should not be negative";
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PendingTask pending_task(from_here, task, delayed_run_time, false);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Push the task to the incoming queue.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock locked(lock_);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the sequence number. The sequence number provides FIFO ordering
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for tasks with the same |delayed_run_time|.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_task.sequence_num = next_sequence_num_++;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post an asynchronous call on the plugin thread to process the task.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (incoming_queue_.empty()) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostRunTasks();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  incoming_queue_.push(pending_task);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_task.task.Reset();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No tasks should be posted after Quit() has been called.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!quit_received_);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginThreadTaskRunner::PostNonNestableDelayedTask(
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& task,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta delay) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All tasks running on this task loop are non-nestable.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PostDelayedTask(from_here, task, delay);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginThreadTaskRunner::RunsTasksOnCurrentThread() const {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In pepper plugins ideally we should use pp::Core::IsMainThread,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but it is problematic because we would need to keep reference to
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Core somewhere, e.g. make the delegate ref-counted.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::PlatformThread::CurrentId() == plugin_thread_id_;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginThreadTaskRunner::PostRunTasks() {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post tasks to the plugin thread when it is availabe or spin the shutdown
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task loop.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_ != NULL) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Closure closure = base::Bind(&PluginThreadTaskRunner::RunTasks, this);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->RunOnPluginThread(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta(),
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &PluginThreadTaskRunner::TaskSpringboard,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new base::Closure(closure));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_.Signal();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginThreadTaskRunner::PostDelayedRunTasks(base::TimeTicks when) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BelongsToCurrentThread());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |delegate_| is updated from the plugin thread only, so it is safe to access
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it here without taking the lock.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_ != NULL) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Schedule RunDelayedTasks() to be called at |when| if it hasn't been
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // scheduled already.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (scheduled_timers_.insert(when).second) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta delay = CalcTimeDelta(when);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Closure closure =
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&PluginThreadTaskRunner::RunDelayedTasks, this, when);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->RunOnPluginThread(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          delay,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &PluginThreadTaskRunner::TaskSpringboard,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new base::Closure(closure));
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Spin the shutdown loop if the task runner has already been detached.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The shutdown loop will pick the tasks to run itself.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_.Signal();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginThreadTaskRunner::ProcessIncomingTasks() {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BelongsToCurrentThread());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Grab all unsorted tasks accomulated so far.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TaskQueue work_queue;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock locked(lock_);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    incoming_queue_.Swap(&work_queue);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!work_queue.empty()) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::PendingTask pending_task = work_queue.front();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    work_queue.pop();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pending_task.delayed_run_time.is_null()) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_task.task.Run();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delayed_queue_.push(pending_task);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginThreadTaskRunner::RunDelayedTasks(base::TimeTicks when) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BelongsToCurrentThread());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduled_timers_.erase(when);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |stopped_| is updated by the plugin thread only, so it is safe to access
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it here without taking the lock.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!stopped_) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessIncomingTasks();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunDueTasks(base::TimeTicks::Now());
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginThreadTaskRunner::RunDueTasks(base::TimeTicks now) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BelongsToCurrentThread());
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run all due tasks.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!delayed_queue_.empty() &&
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         delayed_queue_.top().delayed_run_time <= now) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delayed_queue_.top().task.Run();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delayed_queue_.pop();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post a delayed asynchronous call to the plugin thread to process tasks from
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the delayed queue.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!delayed_queue_.empty()) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeTicks when = delayed_queue_.top().delayed_run_time;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (scheduled_timers_.empty() || when < *scheduled_timers_.begin()) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostDelayedRunTasks(when);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginThreadTaskRunner::RunTasks() {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BelongsToCurrentThread());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |stopped_| is updated by the plugin thread only, so it is safe to access
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it here without taking the lock.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!stopped_) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessIncomingTasks();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunDueTasks(base::TimeTicks::Now());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginThreadTaskRunner::TaskSpringboard(void* data) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure* task = reinterpret_cast<base::Closure*>(data);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task->Run();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete task;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
248