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)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/in_flight_io.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/single_thread_task_runner.h"
1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/task_runner.h"
1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/thread_task_runner_handle.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace disk_cache {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundIO::BackgroundIO(InFlightIO* controller)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : result_(-1), io_completed_(true, false), controller_(controller) {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Runs on the primary thread.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundIO::OnIOSignalled() {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (controller_)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller_->InvokeCallback(this, false);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundIO::Cancel() {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // controller_ may be in use from the background thread at this time.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(controller_lock_);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(controller_);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller_ = NULL;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackgroundIO::~BackgroundIO() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------------
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InFlightIO::InFlightIO()
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    : callback_task_runner_(base::ThreadTaskRunnerHandle::Get()),
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      running_(false),
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      single_thread_(false) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InFlightIO::~InFlightIO() {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Runs on the background thread.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackgroundIO::NotifyController() {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(controller_lock_);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (controller_)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller_->OnIOComplete(this);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InFlightIO::WaitForPendingIO() {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!io_list_.empty()) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Block the current thread until all pending IO completes.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOList::iterator it = io_list_.begin();
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    InvokeCallback(it->get(), true);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InFlightIO::DropPendingIO() {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!io_list_.empty()) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOList::iterator it = io_list_.begin();
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    BackgroundIO* operation = it->get();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operation->Cancel();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(io_list_.find(operation) != io_list_.end());
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_list_.erase(make_scoped_refptr(operation));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Runs on a background thread.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InFlightIO::OnIOComplete(BackgroundIO* operation) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (callback_task_runner_->RunsTasksOnCurrentThread()) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(single_thread_ || !running_);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    single_thread_ = true;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  callback_task_runner_->PostTask(
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      FROM_HERE, base::Bind(&BackgroundIO::OnIOSignalled, operation));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operation->io_completed()->Signal();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Runs on the primary thread.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InFlightIO::InvokeCallback(BackgroundIO* operation, bool cancel_task) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // http://crbug.com/74623
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ThreadRestrictions::ScopedAllowWait allow_wait;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operation->io_completed()->Wait();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  running_ = true;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cancel_task)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operation->Cancel();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure that we remove the operation from the list before invoking the
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callback (so that a subsequent cancel does not invoke the callback again).
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(io_list_.find(operation) != io_list_.end());
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!operation->HasOneRef());
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_list_.erase(make_scoped_refptr(operation));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnOperationComplete(operation, cancel_task);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Runs on the primary thread.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InFlightIO::OnOperationPosted(BackgroundIO* operation) {
10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(callback_task_runner_->RunsTasksOnCurrentThread());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_list_.insert(make_scoped_refptr(operation));
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace disk_cache
114