in_flight_io.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1// Copyright (c) 2012 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/blockfile/in_flight_io.h" 6 7#include "base/bind.h" 8#include "base/location.h" 9#include "base/logging.h" 10#include "base/threading/thread_restrictions.h" 11 12namespace disk_cache { 13 14BackgroundIO::BackgroundIO(InFlightIO* controller) 15 : result_(-1), io_completed_(true, false), controller_(controller) { 16} 17 18// Runs on the primary thread. 19void BackgroundIO::OnIOSignalled() { 20 if (controller_) 21 controller_->InvokeCallback(this, false); 22} 23 24void BackgroundIO::Cancel() { 25 // controller_ may be in use from the background thread at this time. 26 base::AutoLock lock(controller_lock_); 27 DCHECK(controller_); 28 controller_ = NULL; 29} 30 31BackgroundIO::~BackgroundIO() { 32} 33 34// --------------------------------------------------------------------------- 35 36InFlightIO::InFlightIO() 37 : callback_thread_(base::MessageLoopProxy::current()), 38 running_(false), single_thread_(false) { 39} 40 41InFlightIO::~InFlightIO() { 42} 43 44// Runs on the background thread. 45void BackgroundIO::NotifyController() { 46 base::AutoLock lock(controller_lock_); 47 if (controller_) 48 controller_->OnIOComplete(this); 49} 50 51void InFlightIO::WaitForPendingIO() { 52 while (!io_list_.empty()) { 53 // Block the current thread until all pending IO completes. 54 IOList::iterator it = io_list_.begin(); 55 InvokeCallback(it->get(), true); 56 } 57} 58 59void InFlightIO::DropPendingIO() { 60 while (!io_list_.empty()) { 61 IOList::iterator it = io_list_.begin(); 62 BackgroundIO* operation = it->get(); 63 operation->Cancel(); 64 DCHECK(io_list_.find(operation) != io_list_.end()); 65 io_list_.erase(make_scoped_refptr(operation)); 66 } 67} 68 69// Runs on a background thread. 70void InFlightIO::OnIOComplete(BackgroundIO* operation) { 71#ifndef NDEBUG 72 if (callback_thread_->BelongsToCurrentThread()) { 73 DCHECK(single_thread_ || !running_); 74 single_thread_ = true; 75 } 76#endif 77 78 callback_thread_->PostTask(FROM_HERE, 79 base::Bind(&BackgroundIO::OnIOSignalled, 80 operation)); 81 operation->io_completed()->Signal(); 82} 83 84// Runs on the primary thread. 85void InFlightIO::InvokeCallback(BackgroundIO* operation, bool cancel_task) { 86 { 87 // http://crbug.com/74623 88 base::ThreadRestrictions::ScopedAllowWait allow_wait; 89 operation->io_completed()->Wait(); 90 } 91 running_ = true; 92 93 if (cancel_task) 94 operation->Cancel(); 95 96 // Make sure that we remove the operation from the list before invoking the 97 // callback (so that a subsequent cancel does not invoke the callback again). 98 DCHECK(io_list_.find(operation) != io_list_.end()); 99 DCHECK(!operation->HasOneRef()); 100 io_list_.erase(make_scoped_refptr(operation)); 101 OnOperationComplete(operation, cancel_task); 102} 103 104// Runs on the primary thread. 105void InFlightIO::OnOperationPosted(BackgroundIO* operation) { 106 DCHECK(callback_thread_->BelongsToCurrentThread()); 107 io_list_.insert(make_scoped_refptr(operation)); 108} 109 110} // namespace disk_cache 111