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
14namespace disk_cache {
15
16class InFlightIO;
17
18// This class represents a single asynchronous IO operation while it is being
19// bounced between threads.
20class 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.
89class 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