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