Home | History | Annotate | Download | only in disk_cache
      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_IN_FLIGHT_IO_H_
      6 #define NET_DISK_CACHE_IN_FLIGHT_IO_H_
      7 
      8 #include <set>
      9 
     10 #include "base/message_loop/message_loop_proxy.h"
     11 #include "base/synchronization/lock.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   // Notifies the controller about the end of the operation, from the background
     52   // thread.
     53   void NotifyController();
     54 
     55   int result_;  // Final operation result.
     56 
     57  private:
     58   friend class base::RefCountedThreadSafe<BackgroundIO>;
     59 
     60   // An event to signal when the operation completes.
     61   base::WaitableEvent io_completed_;
     62   InFlightIO* controller_;  // The controller that tracks all operations.
     63   base::Lock controller_lock_;  // A lock protecting clearing of controller_.
     64 
     65   DISALLOW_COPY_AND_ASSIGN(BackgroundIO);
     66 };
     67 
     68 // This class keeps track of asynchronous IO operations. A single instance
     69 // of this class is meant to be used to start an asynchronous operation (using
     70 // PostXX, exposed by a derived class). This class will post the operation to a
     71 // worker thread, hanlde the notification when the operation finishes and
     72 // perform the callback on the same thread that was used to start the operation.
     73 //
     74 // The regular sequence of calls is:
     75 //                 Thread_1                          Worker_thread
     76 //    1.     DerivedInFlightIO::PostXX()
     77 //    2.                         -> PostTask ->
     78 //    3.    InFlightIO::OnOperationPosted()
     79 //    4.                                        DerivedBackgroundIO::XX()
     80 //    5.                                         IO operation completes
     81 //    6.                                       InFlightIO::OnIOComplete()
     82 //    7.                         <- PostTask <-
     83 //    8.  BackgroundIO::OnIOSignalled()
     84 //    9.  InFlightIO::InvokeCallback()
     85 //   10. DerivedInFlightIO::OnOperationComplete()
     86 //   11.       invoke callback
     87 //
     88 // Shutdown is a special case that is handled though WaitForPendingIO() instead
     89 // of just waiting for step 7.
     90 class InFlightIO {
     91  public:
     92   InFlightIO();
     93   virtual ~InFlightIO();
     94 
     95   // Blocks the current thread until all IO operations tracked by this object
     96   // complete.
     97   void WaitForPendingIO();
     98 
     99   // Drops current pending operations without waiting for them to complete.
    100   void DropPendingIO();
    101 
    102   // Called on a background thread when |operation| completes.
    103   void OnIOComplete(BackgroundIO* operation);
    104 
    105   // Invokes the users' completion callback at the end of the IO operation.
    106   // |cancel_task| is true if the actual task posted to the thread is still
    107   // queued (because we are inside WaitForPendingIO), and false if said task is
    108   // the one performing the call.
    109   void InvokeCallback(BackgroundIO* operation, bool cancel_task);
    110 
    111  protected:
    112   // This method is called to signal the completion of the |operation|. |cancel|
    113   // is true if the operation is being cancelled. This method is called on the
    114   // thread that created this object.
    115   virtual void OnOperationComplete(BackgroundIO* operation, bool cancel) = 0;
    116 
    117   // Signals this object that the derived class just posted the |operation| to
    118   // be executed on a background thread. This method must be called on the same
    119   // thread used to create this object.
    120   void OnOperationPosted(BackgroundIO* operation);
    121 
    122  private:
    123   typedef std::set<scoped_refptr<BackgroundIO> > IOList;
    124 
    125   IOList io_list_;  // List of pending, in-flight io operations.
    126   scoped_refptr<base::MessageLoopProxy> callback_thread_;
    127 
    128   bool running_;  // True after the first posted operation completes.
    129   bool single_thread_;  // True if we only have one thread.
    130 
    131   DISALLOW_COPY_AND_ASSIGN(InFlightIO);
    132 };
    133 
    134 }  // namespace disk_cache
    135 
    136 #endif  // NET_DISK_CACHE_IN_FLIGHT_IO_H_
    137