// Copyright 2013 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 "base/message_loop/incoming_task_queue.h"

#include <limits>
#include <utility>

#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/time/time.h"
#include "build_config.h"

namespace base {
namespace internal {

namespace {

#if DCHECK_IS_ON()
// Delays larger than this are often bogus, and a warning should be emitted in
// debug builds to warn developers.  http://crbug.com/450045
constexpr TimeDelta kTaskDelayWarningThreshold = TimeDelta::FromDays(14);
#endif

// Returns true if MessagePump::ScheduleWork() must be called one
// time for every task that is added to the MessageLoop incoming queue.
bool AlwaysNotifyPump(MessageLoop::Type type) {
#if defined(OS_ANDROID)
  // The Android UI message loop needs to get notified each time a task is
  // added
  // to the incoming queue.
  return type == MessageLoop::TYPE_UI || type == MessageLoop::TYPE_JAVA;
#else
  return false;
#endif
}

TimeTicks CalculateDelayedRuntime(TimeDelta delay) {
  TimeTicks delayed_run_time;
  if (delay > TimeDelta())
    delayed_run_time = TimeTicks::Now() + delay;
  else
    DCHECK_EQ(delay.InMilliseconds(), 0) << "delay should not be negative";
  return delayed_run_time;
}

}  // namespace

IncomingTaskQueue::IncomingTaskQueue(MessageLoop* message_loop)
    : always_schedule_work_(AlwaysNotifyPump(message_loop->type())),
      triage_tasks_(this),
      delayed_tasks_(this),
      deferred_tasks_(this),
      message_loop_(message_loop) {
  // The constructing sequence is not necessarily the running sequence in the
  // case of base::Thread.
  DETACH_FROM_SEQUENCE(sequence_checker_);
}

bool IncomingTaskQueue::AddToIncomingQueue(const Location& from_here,
                                           OnceClosure task,
                                           TimeDelta delay,
                                           Nestable nestable) {
  // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167
  // for details.
  CHECK(task);
  DLOG_IF(WARNING, delay > kTaskDelayWarningThreshold)
      << "Requesting super-long task delay period of " << delay.InSeconds()
      << " seconds from here: " << from_here.ToString();

  PendingTask pending_task(from_here, std::move(task),
                           CalculateDelayedRuntime(delay), nestable);
#if defined(OS_WIN)
  // We consider the task needs a high resolution timer if the delay is
  // more than 0 and less than 32ms. This caps the relative error to
  // less than 50% : a 33ms wait can wake at 48ms since the default
  // resolution on Windows is between 10 and 15ms.
  if (delay > TimeDelta() &&
      delay.InMilliseconds() < (2 * Time::kMinLowResolutionThresholdMs)) {
    pending_task.is_high_res = true;
  }
#endif
  return PostPendingTask(&pending_task);
}

void IncomingTaskQueue::WillDestroyCurrentMessageLoop() {
  {
    AutoLock auto_lock(incoming_queue_lock_);
    accept_new_tasks_ = false;
  }
  {
    AutoLock auto_lock(message_loop_lock_);
    message_loop_ = nullptr;
  }
}

void IncomingTaskQueue::StartScheduling() {
  bool schedule_work;
  {
    AutoLock lock(incoming_queue_lock_);
    DCHECK(!is_ready_for_scheduling_);
    DCHECK(!message_loop_scheduled_);
    is_ready_for_scheduling_ = true;
    schedule_work = !incoming_queue_.empty();
    if (schedule_work)
      message_loop_scheduled_ = true;
  }
  if (schedule_work) {
    DCHECK(message_loop_);
    AutoLock auto_lock(message_loop_lock_);
    message_loop_->ScheduleWork();
  }
}

IncomingTaskQueue::~IncomingTaskQueue() {
  // Verify that WillDestroyCurrentMessageLoop() has been called.
  DCHECK(!message_loop_);
}

void IncomingTaskQueue::RunTask(PendingTask* pending_task) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  task_annotator_.RunTask("MessageLoop::PostTask", pending_task);
}

IncomingTaskQueue::TriageQueue::TriageQueue(IncomingTaskQueue* outer)
    : outer_(outer) {}

IncomingTaskQueue::TriageQueue::~TriageQueue() = default;

const PendingTask& IncomingTaskQueue::TriageQueue::Peek() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  ReloadFromIncomingQueueIfEmpty();
  DCHECK(!queue_.empty());
  return queue_.front();
}

PendingTask IncomingTaskQueue::TriageQueue::Pop() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  ReloadFromIncomingQueueIfEmpty();
  DCHECK(!queue_.empty());
  PendingTask pending_task = std::move(queue_.front());
  queue_.pop();

  if (pending_task.is_high_res)
    --outer_->pending_high_res_tasks_;

  return pending_task;
}

bool IncomingTaskQueue::TriageQueue::HasTasks() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  ReloadFromIncomingQueueIfEmpty();
  return !queue_.empty();
}

void IncomingTaskQueue::TriageQueue::Clear() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  // Previously, MessageLoop would delete all tasks including delayed and
  // deferred tasks in a single round before attempting to reload from the
  // incoming queue to see if more tasks remained. This gave it a chance to
  // assess whether or not clearing should continue. As a result, while
  // reloading is automatic for getting and seeing if tasks exist, it is not
  // automatic for Clear().
  while (!queue_.empty()) {
    PendingTask pending_task = std::move(queue_.front());
    queue_.pop();

    if (pending_task.is_high_res)
      --outer_->pending_high_res_tasks_;

    if (!pending_task.delayed_run_time.is_null()) {
      outer_->delayed_tasks().Push(std::move(pending_task));
    }
  }
}

void IncomingTaskQueue::TriageQueue::ReloadFromIncomingQueueIfEmpty() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  if (queue_.empty()) {
    // TODO(robliao): Since these high resolution tasks aren't yet in the
    // delayed queue, they technically shouldn't trigger high resolution timers
    // until they are.
    outer_->pending_high_res_tasks_ += outer_->ReloadWorkQueue(&queue_);
  }
}

IncomingTaskQueue::DelayedQueue::DelayedQueue(IncomingTaskQueue* outer)
    : outer_(outer) {}

IncomingTaskQueue::DelayedQueue::~DelayedQueue() = default;

void IncomingTaskQueue::DelayedQueue::Push(PendingTask pending_task) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);

  if (pending_task.is_high_res)
    ++outer_->pending_high_res_tasks_;

  queue_.push(std::move(pending_task));
}

const PendingTask& IncomingTaskQueue::DelayedQueue::Peek() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  DCHECK(!queue_.empty());
  return queue_.top();
}

PendingTask IncomingTaskQueue::DelayedQueue::Pop() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  DCHECK(!queue_.empty());
  PendingTask delayed_task = std::move(const_cast<PendingTask&>(queue_.top()));
  queue_.pop();

  if (delayed_task.is_high_res)
    --outer_->pending_high_res_tasks_;

  return delayed_task;
}

bool IncomingTaskQueue::DelayedQueue::HasTasks() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  // TODO(robliao): The other queues don't check for IsCancelled(). Should they?
  while (!queue_.empty() && Peek().task.IsCancelled())
    Pop();

  return !queue_.empty();
}

void IncomingTaskQueue::DelayedQueue::Clear() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  while (!queue_.empty())
    Pop();
}

IncomingTaskQueue::DeferredQueue::DeferredQueue(IncomingTaskQueue* outer)
    : outer_(outer) {}

IncomingTaskQueue::DeferredQueue::~DeferredQueue() = default;

void IncomingTaskQueue::DeferredQueue::Push(PendingTask pending_task) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);

  // TODO(robliao): These tasks should not count towards the high res task count
  // since they are no longer in the delayed queue.
  if (pending_task.is_high_res)
    ++outer_->pending_high_res_tasks_;

  queue_.push(std::move(pending_task));
}

const PendingTask& IncomingTaskQueue::DeferredQueue::Peek() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  DCHECK(!queue_.empty());
  return queue_.front();
}

PendingTask IncomingTaskQueue::DeferredQueue::Pop() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  DCHECK(!queue_.empty());
  PendingTask deferred_task = std::move(queue_.front());
  queue_.pop();

  if (deferred_task.is_high_res)
    --outer_->pending_high_res_tasks_;

  return deferred_task;
}

bool IncomingTaskQueue::DeferredQueue::HasTasks() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  return !queue_.empty();
}

void IncomingTaskQueue::DeferredQueue::Clear() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(outer_->sequence_checker_);
  while (!queue_.empty())
    Pop();
}

bool IncomingTaskQueue::PostPendingTask(PendingTask* pending_task) {
  // Warning: Don't try to short-circuit, and handle this thread's tasks more
  // directly, as it could starve handling of foreign threads.  Put every task
  // into this queue.
  bool accept_new_tasks;
  bool schedule_work = false;
  {
    AutoLock auto_lock(incoming_queue_lock_);
    accept_new_tasks = accept_new_tasks_;
    if (accept_new_tasks)
      schedule_work = PostPendingTaskLockRequired(pending_task);
  }

  if (!accept_new_tasks) {
    // Clear the pending task outside of |incoming_queue_lock_| to prevent any
    // chance of self-deadlock if destroying a task also posts a task to this
    // queue.
    DCHECK(!schedule_work);
    pending_task->task.Reset();
    return false;
  }

  // Wake up the message loop and schedule work. This is done outside
  // |incoming_queue_lock_| to allow for multiple post tasks to occur while
  // ScheduleWork() is running. For platforms (e.g. Android) that require one
  // call to ScheduleWork() for each task, all pending tasks may serialize
  // within the ScheduleWork() call. As a result, holding a lock to maintain the
  // lifetime of |message_loop_| is less of a concern.
  if (schedule_work) {
    // Ensures |message_loop_| isn't destroyed while running.
    AutoLock auto_lock(message_loop_lock_);
    if (message_loop_)
      message_loop_->ScheduleWork();
  }

  return true;
}

bool IncomingTaskQueue::PostPendingTaskLockRequired(PendingTask* pending_task) {
  incoming_queue_lock_.AssertAcquired();

#if defined(OS_WIN)
  if (pending_task->is_high_res)
    ++high_res_task_count_;
#endif

  // Initialize the sequence number. The sequence number is used for delayed
  // tasks (to facilitate FIFO sorting when two tasks have the same
  // delayed_run_time value) and for identifying the task in about:tracing.
  pending_task->sequence_num = next_sequence_num_++;

  task_annotator_.DidQueueTask("MessageLoop::PostTask", *pending_task);

  bool was_empty = incoming_queue_.empty();
  incoming_queue_.push(std::move(*pending_task));

  if (is_ready_for_scheduling_ &&
      (always_schedule_work_ || (!message_loop_scheduled_ && was_empty))) {
    // After we've scheduled the message loop, we do not need to do so again
    // until we know it has processed all of the work in our queue and is
    // waiting for more work again. The message loop will always attempt to
    // reload from the incoming queue before waiting again so we clear this
    // flag in ReloadWorkQueue().
    message_loop_scheduled_ = true;
    return true;
  }
  return false;
}

int IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // Make sure no tasks are lost.
  DCHECK(work_queue->empty());

  // Acquire all we can from the inter-thread queue with one lock acquisition.
  AutoLock lock(incoming_queue_lock_);
  if (incoming_queue_.empty()) {
    // If the loop attempts to reload but there are no tasks in the incoming
    // queue, that means it will go to sleep waiting for more work. If the
    // incoming queue becomes nonempty we need to schedule it again.
    message_loop_scheduled_ = false;
  } else {
    incoming_queue_.swap(*work_queue);
  }
  // Reset the count of high resolution tasks since our queue is now empty.
  int high_res_tasks = high_res_task_count_;
  high_res_task_count_ = 0;
  return high_res_tasks;
}

}  // namespace internal
}  // namespace base
