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 11 BackgroundIO::BackgroundIO(InFlightIO* controller) 12 : controller_(controller), result_(-1), io_completed_(true, false) { 13 } 14 15 // Runs on the primary thread. 16 void BackgroundIO::OnIOSignalled() { 17 if (controller_) 18 controller_->InvokeCallback(this, false); 19 } 20 21 void BackgroundIO::Cancel() { 22 DCHECK(controller_); 23 controller_ = NULL; 24 } 25 26 BackgroundIO::~BackgroundIO() {} 27 28 // Runs on the background thread. 29 void BackgroundIO::NotifyController() { 30 controller_->OnIOComplete(this); 31 } 32 33 // --------------------------------------------------------------------------- 34 35 InFlightIO::InFlightIO() 36 : callback_thread_(base::MessageLoopProxy::CreateForCurrentThread()), 37 running_(false), single_thread_(false) { 38 } 39 40 InFlightIO::~InFlightIO() { 41 } 42 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. 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. 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. 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