in_flight_io.cc revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/disk_cache/in_flight_io.h"
6
7#include "base/logging.h"
8
9namespace disk_cache {
10
11BackgroundIO::BackgroundIO(InFlightIO* controller)
12    : controller_(controller), result_(-1), io_completed_(true, false) {
13}
14
15// Runs on the primary thread.
16void BackgroundIO::OnIOSignalled() {
17  if (controller_)
18    controller_->InvokeCallback(this, false);
19}
20
21void BackgroundIO::Cancel() {
22  DCHECK(controller_);
23  controller_ = NULL;
24}
25
26BackgroundIO::~BackgroundIO() {}
27
28// Runs on the background thread.
29void BackgroundIO::NotifyController() {
30  controller_->OnIOComplete(this);
31}
32
33// ---------------------------------------------------------------------------
34
35InFlightIO::InFlightIO()
36    : callback_thread_(base::MessageLoopProxy::CreateForCurrentThread()),
37      running_(false), single_thread_(false) {
38}
39
40InFlightIO::~InFlightIO() {
41}
42
43void InFlightIO::WaitForPendingIO() {
44  while (!io_list_.empty()) {
45    // Block the current thread until all pending IO completes.
46    IOList::iterator it = io_list_.begin();
47    InvokeCallback(*it, true);
48  }
49}
50
51// Runs on a background thread.
52void InFlightIO::OnIOComplete(BackgroundIO* operation) {
53#ifndef NDEBUG
54  if (callback_thread_->BelongsToCurrentThread()) {
55    DCHECK(single_thread_ || !running_);
56    single_thread_ = true;
57  }
58  running_ = true;
59#endif
60
61  callback_thread_->PostTask(FROM_HERE,
62                             NewRunnableMethod(operation,
63                                               &BackgroundIO::OnIOSignalled));
64  operation->io_completed()->Signal();
65}
66
67// Runs on the primary thread.
68void InFlightIO::InvokeCallback(BackgroundIO* operation, bool cancel_task) {
69  operation->io_completed()->Wait();
70
71  if (cancel_task)
72    operation->Cancel();
73
74  // Make sure that we remove the operation from the list before invoking the
75  // callback (so that a subsequent cancel does not invoke the callback again).
76  DCHECK(io_list_.find(operation) != io_list_.end());
77  io_list_.erase(make_scoped_refptr(operation));
78  OnOperationComplete(operation, cancel_task);
79}
80
81// Runs on the primary thread.
82void InFlightIO::OnOperationPosted(BackgroundIO* operation) {
83  DCHECK(callback_thread_->BelongsToCurrentThread());
84  io_list_.insert(make_scoped_refptr(operation));
85}
86
87}  // namespace disk_cache
88