15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifndef NET_DISK_CACHE_BLOCKFILE_IN_FLIGHT_IO_H_
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define NET_DISK_CACHE_BLOCKFILE_IN_FLIGHT_IO_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/memory/ref_counted.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace base {
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class TaskRunner;
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace base
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace disk_cache {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InFlightIO;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class represents a single asynchronous IO operation while it is being
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bounced between threads.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BackgroundIO : public base::RefCountedThreadSafe<BackgroundIO> {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Other than the actual parameters for the IO operation (including the
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |callback| that must be notified at the end), we need the controller that
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is keeping track of all operations. When done, we notify the controller
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (we do NOT invoke the callback), in the worker thead that completed the
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // operation.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit BackgroundIO(InFlightIO* controller);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This method signals the controller that this operation is finished, in the
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // original thread. In practice, this is a RunableMethod that allows
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cancellation.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnIOSignalled();
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allows the cancellation of the task to notify the controller (step number 8
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the diagram below). In practice, if the controller waits for the
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // operation to finish it doesn't have to wait for the final task to be
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // processed by the message loop so calling this method prevents its delivery.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that this method is not intended to cancel the actual IO operation or
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to prevent the first notification to take place (OnIOComplete).
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Cancel();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result() { return result_; }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent* io_completed() {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &io_completed_;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BackgroundIO();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the controller about the end of the operation, from the background
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyController();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result_;  // Final operation result.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<BackgroundIO>;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An event to signal when the operation completes.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent io_completed_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InFlightIO* controller_;  // The controller that tracks all operations.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock controller_lock_;  // A lock protecting clearing of controller_.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BackgroundIO);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class keeps track of asynchronous IO operations. A single instance
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of this class is meant to be used to start an asynchronous operation (using
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PostXX, exposed by a derived class). This class will post the operation to a
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// worker thread, hanlde the notification when the operation finishes and
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// perform the callback on the same thread that was used to start the operation.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The regular sequence of calls is:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                 Thread_1                          Worker_thread
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    1.     DerivedInFlightIO::PostXX()
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    2.                         -> PostTask ->
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    3.    InFlightIO::OnOperationPosted()
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    4.                                        DerivedBackgroundIO::XX()
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    5.                                         IO operation completes
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    6.                                       InFlightIO::OnIOComplete()
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    7.                         <- PostTask <-
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    8.  BackgroundIO::OnIOSignalled()
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    9.  InFlightIO::InvokeCallback()
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   10. DerivedInFlightIO::OnOperationComplete()
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   11.       invoke callback
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Shutdown is a special case that is handled though WaitForPendingIO() instead
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of just waiting for step 7.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InFlightIO {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InFlightIO();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~InFlightIO();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Blocks the current thread until all IO operations tracked by this object
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // complete.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForPendingIO();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Drops current pending operations without waiting for them to complete.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DropPendingIO();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on a background thread when |operation| completes.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnIOComplete(BackgroundIO* operation);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invokes the users' completion callback at the end of the IO operation.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |cancel_task| is true if the actual task posted to the thread is still
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // queued (because we are inside WaitForPendingIO), and false if said task is
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the one performing the call.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InvokeCallback(BackgroundIO* operation, bool cancel_task);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This method is called to signal the completion of the |operation|. |cancel|
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is true if the operation is being cancelled. This method is called on the
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread that created this object.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnOperationComplete(BackgroundIO* operation, bool cancel) = 0;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Signals this object that the derived class just posted the |operation| to
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be executed on a background thread. This method must be called on the same
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread used to create this object.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnOperationPosted(BackgroundIO* operation);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::set<scoped_refptr<BackgroundIO> > IOList;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IOList io_list_;  // List of pending, in-flight io operations.
13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<base::TaskRunner> callback_task_runner_;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool running_;  // True after the first posted operation completes.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool single_thread_;  // True if we only have one thread.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(InFlightIO);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace disk_cache
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  // NET_DISK_CACHE_BLOCKFILE_IN_FLIGHT_IO_H_
141