// Copyright (c) 2012 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 "net/disk_cache/blockfile/in_flight_io.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"

namespace disk_cache {

BackgroundIO::BackgroundIO(InFlightIO* controller)
    : result_(-1),
      io_completed_(base::WaitableEvent::ResetPolicy::MANUAL,
                    base::WaitableEvent::InitialState::NOT_SIGNALED),
      controller_(controller) {}

// Runs on the primary thread.
void BackgroundIO::OnIOSignalled() {
  if (controller_)
    controller_->InvokeCallback(this, false);
}

void BackgroundIO::Cancel() {
  // controller_ may be in use from the background thread at this time.
  base::AutoLock lock(controller_lock_);
  DCHECK(controller_);
  controller_ = NULL;
}

BackgroundIO::~BackgroundIO() = default;

// ---------------------------------------------------------------------------

InFlightIO::InFlightIO()
    : callback_task_runner_(base::ThreadTaskRunnerHandle::Get()),
      running_(false) {}

InFlightIO::~InFlightIO() = default;

// Runs on the background thread.
void BackgroundIO::NotifyController() {
  base::AutoLock lock(controller_lock_);
  if (controller_)
    controller_->OnIOComplete(this);
}

void InFlightIO::WaitForPendingIO() {
  while (!io_list_.empty()) {
    // Block the current thread until all pending IO completes.
    IOList::iterator it = io_list_.begin();
    InvokeCallback(it->get(), true);
  }
}

void InFlightIO::DropPendingIO() {
  while (!io_list_.empty()) {
    IOList::iterator it = io_list_.begin();
    BackgroundIO* operation = it->get();
    operation->Cancel();
    DCHECK(io_list_.find(operation) != io_list_.end());
    io_list_.erase(base::WrapRefCounted(operation));
  }
}

// Runs in a background sequence.
void InFlightIO::OnIOComplete(BackgroundIO* operation) {
#if DCHECK_IS_ON()
  if (callback_task_runner_->RunsTasksInCurrentSequence()) {
    DCHECK(single_thread_ || !running_);
    single_thread_ = true;
  }
#endif

  callback_task_runner_->PostTask(
      FROM_HERE, base::Bind(&BackgroundIO::OnIOSignalled, operation));
  operation->io_completed()->Signal();
}

// Runs on the primary thread.
void InFlightIO::InvokeCallback(BackgroundIO* operation, bool cancel_task) {
  {
    // http://crbug.com/74623
    base::ThreadRestrictions::ScopedAllowWait allow_wait;
    operation->io_completed()->Wait();
  }
  running_ = true;

  if (cancel_task)
    operation->Cancel();

  // Make sure that we remove the operation from the list before invoking the
  // callback (so that a subsequent cancel does not invoke the callback again).
  DCHECK(io_list_.find(operation) != io_list_.end());
  DCHECK(!operation->HasOneRef());
  io_list_.erase(base::WrapRefCounted(operation));
  OnOperationComplete(operation, cancel_task);
}

// Runs on the primary thread.
void InFlightIO::OnOperationPosted(BackgroundIO* operation) {
  DCHECK(callback_task_runner_->RunsTasksInCurrentSequence());
  io_list_.insert(base::WrapRefCounted(operation));
}

}  // namespace disk_cache
