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
9 namespace disk_cache {
10
BackgroundIO(InFlightIO * controller)11 BackgroundIO::BackgroundIO(InFlightIO* controller)
12 : controller_(controller), result_(-1), io_completed_(true, false) {
13 }
14
15 // Runs on the primary thread.
OnIOSignalled()16 void BackgroundIO::OnIOSignalled() {
17 if (controller_)
18 controller_->InvokeCallback(this, false);
19 }
20
Cancel()21 void BackgroundIO::Cancel() {
22 DCHECK(controller_);
23 controller_ = NULL;
24 }
25
~BackgroundIO()26 BackgroundIO::~BackgroundIO() {}
27
28 // Runs on the background thread.
NotifyController()29 void BackgroundIO::NotifyController() {
30 controller_->OnIOComplete(this);
31 }
32
33 // ---------------------------------------------------------------------------
34
InFlightIO()35 InFlightIO::InFlightIO()
36 : callback_thread_(base::MessageLoopProxy::CreateForCurrentThread()),
37 running_(false), single_thread_(false) {
38 }
39
~InFlightIO()40 InFlightIO::~InFlightIO() {
41 }
42
WaitForPendingIO()43 void 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.
OnIOComplete(BackgroundIO * operation)52 void 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.
InvokeCallback(BackgroundIO * operation,bool cancel_task)68 void 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.
OnOperationPosted(BackgroundIO * operation)82 void InFlightIO::OnOperationPosted(BackgroundIO* operation) {
83 DCHECK(callback_thread_->BelongsToCurrentThread());
84 io_list_.insert(make_scoped_refptr(operation));
85 }
86
87 } // namespace disk_cache
88