Home | History | Annotate | Download | only in disk_cache
      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