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