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