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 #ifndef NET_DISK_CACHE_IN_FLIGHT_IO_H_
      6 #define NET_DISK_CACHE_IN_FLIGHT_IO_H_
      7 #pragma once
      8 
      9 #include <set>
     10 
     11 #include "base/message_loop_proxy.h"
     12 #include "base/synchronization/waitable_event.h"
     13 
     14 namespace disk_cache {
     15 
     16 class InFlightIO;
     17 
     18 // This class represents a single asynchronous IO operation while it is being
     19 // bounced between threads.
     20 class BackgroundIO : public base::RefCountedThreadSafe<BackgroundIO> {
     21  public:
     22   // Other than the actual parameters for the IO operation (including the
     23   // |callback| that must be notified at the end), we need the controller that
     24   // is keeping track of all operations. When done, we notify the controller
     25   // (we do NOT invoke the callback), in the worker thead that completed the
     26   // operation.
     27   explicit BackgroundIO(InFlightIO* controller);
     28 
     29   // This method signals the controller that this operation is finished, in the
     30   // original thread. In practice, this is a RunableMethod that allows
     31   // cancellation.
     32   void OnIOSignalled();
     33 
     34   // Allows the cancellation of the task to notify the controller (step number 8
     35   // in the diagram below). In practice, if the controller waits for the
     36   // operation to finish it doesn't have to wait for the final task to be
     37   // processed by the message loop so calling this method prevents its delivery.
     38   // Note that this method is not intended to cancel the actual IO operation or
     39   // to prevent the first notification to take place (OnIOComplete).
     40   void Cancel();
     41 
     42   int result() { return result_; }
     43 
     44   base::WaitableEvent* io_completed() {
     45     return &io_completed_;
     46   }
     47 
     48  protected:
     49   virtual ~BackgroundIO();
     50 
     51   InFlightIO* controller_;  // The controller that tracks all operations.
     52   int result_;  // Final operation result.
     53 
     54  private:
     55   friend class base::RefCountedThreadSafe<BackgroundIO>;
     56 
     57   // Notifies the controller about the end of the operation, from the background
     58   // thread.
     59   void NotifyController();
     60 
     61   // An event to signal when the operation completes.
     62   base::WaitableEvent io_completed_;
     63 
     64   DISALLOW_COPY_AND_ASSIGN(BackgroundIO);
     65 };
     66 
     67 // This class keeps track of asynchronous IO operations. A single instance
     68 // of this class is meant to be used to start an asynchronous operation (using
     69 // PostXX, exposed by a derived class). This class will post the operation to a
     70 // worker thread, hanlde the notification when the operation finishes and
     71 // perform the callback on the same thread that was used to start the operation.
     72 //
     73 // The regular sequence of calls is:
     74 //                 Thread_1                          Worker_thread
     75 //    1.     DerivedInFlightIO::PostXX()
     76 //    2.                         -> PostTask ->
     77 //    3.    InFlightIO::OnOperationPosted()
     78 //    4.                                        DerivedBackgroundIO::XX()
     79 //    5.                                         IO operation completes
     80 //    6.                                       InFlightIO::OnIOComplete()
     81 //    7.                         <- PostTask <-
     82 //    8.  BackgroundIO::OnIOSignalled()
     83 //    9.  InFlightIO::InvokeCallback()
     84 //   10. DerivedInFlightIO::OnOperationComplete()
     85 //   11.       invoke callback
     86 //
     87 // Shutdown is a special case that is handled though WaitForPendingIO() instead
     88 // of just waiting for step 7.
     89 class InFlightIO {
     90  public:
     91   InFlightIO();
     92   virtual ~InFlightIO();
     93 
     94   // Blocks the current thread until all IO operations tracked by this object
     95   // complete.
     96   void WaitForPendingIO();
     97 
     98   // Called on a background thread when |operation| completes.
     99   void OnIOComplete(BackgroundIO* operation);
    100 
    101   // Invokes the users' completion callback at the end of the IO operation.
    102   // |cancel_task| is true if the actual task posted to the thread is still
    103   // queued (because we are inside WaitForPendingIO), and false if said task is
    104   // the one performing the call.
    105   void InvokeCallback(BackgroundIO* operation, bool cancel_task);
    106 
    107  protected:
    108   // This method is called to signal the completion of the |operation|. |cancel|
    109   // is true if the operation is being cancelled. This method is called on the
    110   // thread that created this object.
    111   virtual void OnOperationComplete(BackgroundIO* operation, bool cancel) = 0;
    112 
    113   // Signals this object that the derived class just posted the |operation| to
    114   // be executed on a background thread. This method must be called on the same
    115   // thread used to create this object.
    116   void OnOperationPosted(BackgroundIO* operation);
    117 
    118  private:
    119   typedef std::set<scoped_refptr<BackgroundIO> > IOList;
    120 
    121   IOList io_list_;  // List of pending, in-flight io operations.
    122   scoped_refptr<base::MessageLoopProxy> callback_thread_;
    123 
    124   bool running_;  // True after the first posted operation completes.
    125   bool single_thread_;  // True if we only have one thread.
    126 
    127   DISALLOW_COPY_AND_ASSIGN(InFlightIO);
    128 };
    129 
    130 }  // namespace disk_cache
    131 
    132 #endif  // NET_DISK_CACHE_IN_FLIGHT_IO_H_
    133