xref: /aosp_15_r20/external/cronet/net/dns/serial_worker.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef NET_DNS_SERIAL_WORKER_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_DNS_SERIAL_WORKER_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <memory>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/sequence_checker.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/task/task_traits.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/timer/timer.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/base/backoff_entry.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h"
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace net {
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker // `SerialWorker` executes a job on `ThreadPool` serially -- **one at a time**.
22*6777b538SAndroid Build Coastguard Worker // On `WorkNow()`, a `WorkItem` is created using `CreateWorkItem()` and sent to
23*6777b538SAndroid Build Coastguard Worker // the `ThreadPool`. There, a call to `DoWork()` is made. On completion of work,
24*6777b538SAndroid Build Coastguard Worker // `OnWorkFinished()` is called on the origin thread (if the `SerialWorker` is
25*6777b538SAndroid Build Coastguard Worker // still alive), passing back the `WorkItem` to allow retrieving any results or
26*6777b538SAndroid Build Coastguard Worker // passed objects. If `WorkNow()` is called (1 or more times) while a `WorkItem`
27*6777b538SAndroid Build Coastguard Worker // is already under way, after completion of the work and before any call is
28*6777b538SAndroid Build Coastguard Worker // made to `OnWorkFinished()` the same `WorkItem` will be passed back to the
29*6777b538SAndroid Build Coastguard Worker // `ThreadPool`, and `DoWork()` will be called once more.
30*6777b538SAndroid Build Coastguard Worker //
31*6777b538SAndroid Build Coastguard Worker // If |OnWorkFinished| returns a failure and |max_number_of_retries|
32*6777b538SAndroid Build Coastguard Worker // is non-zero, retries will be scheduled according to the |backoff_policy|.
33*6777b538SAndroid Build Coastguard Worker // A default backoff policy is used if one is not provided.
34*6777b538SAndroid Build Coastguard Worker //
35*6777b538SAndroid Build Coastguard Worker // This behavior is designed for updating a result after some trigger, for
36*6777b538SAndroid Build Coastguard Worker // example reading a file once FilePathWatcher indicates it changed.
37*6777b538SAndroid Build Coastguard Worker //
38*6777b538SAndroid Build Coastguard Worker // Derived classes should store results of work in the `WorkItem` and retrieve
39*6777b538SAndroid Build Coastguard Worker // results from it when passed back to `OnWorkFinished()`. The `SerialWorker` is
40*6777b538SAndroid Build Coastguard Worker // guaranteed to only run one `WorkItem` at a time, always passing it back to
41*6777b538SAndroid Build Coastguard Worker // `OnWorkFinished()` before calling `CreateWorkItem()` again. Therefore, a
42*6777b538SAndroid Build Coastguard Worker // derived class may safely pass objects between `WorkItem`s, or even reuse the
43*6777b538SAndroid Build Coastguard Worker // same `WorkItem`, to allow storing helper objects directly in the `WorkItem`.
44*6777b538SAndroid Build Coastguard Worker // However, it is not guaranteed that the `SerialWorker` will remain alive while
45*6777b538SAndroid Build Coastguard Worker // the `WorkItem` runs. Therefore, the `WorkItem` should never access any memory
46*6777b538SAndroid Build Coastguard Worker // owned by the `SerialWorker` or derived class.
47*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE SerialWorker {
48*6777b538SAndroid Build Coastguard Worker  public:
49*6777b538SAndroid Build Coastguard Worker   // A work item that will be passed to and run on the `ThreadPool` (potentially
50*6777b538SAndroid Build Coastguard Worker   // multiple times if the `SerialWorker` needs to run again immediately) and
51*6777b538SAndroid Build Coastguard Worker   // then passed back to the origin thread on completion. Expected usage is to
52*6777b538SAndroid Build Coastguard Worker   // store any parameters, results, and helper objects in the `WorkItem` and
53*6777b538SAndroid Build Coastguard Worker   // read results from it when passed back to the origin thread.
54*6777b538SAndroid Build Coastguard Worker   //
55*6777b538SAndroid Build Coastguard Worker   // `SerialWorker` calls `FollowupWork()` *on the origin thread* after calling
56*6777b538SAndroid Build Coastguard Worker   // `DoWork()` on the `ThreadPool` to asynchronously handle any work that must
57*6777b538SAndroid Build Coastguard Worker   // be part of the serialization but that cannot run on a worker thread.
58*6777b538SAndroid Build Coastguard Worker   class NET_EXPORT_PRIVATE WorkItem {
59*6777b538SAndroid Build Coastguard Worker    public:
60*6777b538SAndroid Build Coastguard Worker     virtual ~WorkItem() = default;
61*6777b538SAndroid Build Coastguard Worker     virtual void DoWork() = 0;
62*6777b538SAndroid Build Coastguard Worker     virtual void FollowupWork(base::OnceClosure closure);
63*6777b538SAndroid Build Coastguard Worker   };
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker   explicit SerialWorker(
66*6777b538SAndroid Build Coastguard Worker       int max_number_of_retries = 0,
67*6777b538SAndroid Build Coastguard Worker       const net::BackoffEntry::Policy* backoff_policy = nullptr);
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker   SerialWorker(const SerialWorker&) = delete;
70*6777b538SAndroid Build Coastguard Worker   SerialWorker& operator=(const SerialWorker&) = delete;
71*6777b538SAndroid Build Coastguard Worker 
72*6777b538SAndroid Build Coastguard Worker   // Unless already scheduled, post |DoWork| to ThreadPool.
73*6777b538SAndroid Build Coastguard Worker   // Made virtual to allow mocking.
74*6777b538SAndroid Build Coastguard Worker   virtual void WorkNow();
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker   // Stop scheduling jobs.
77*6777b538SAndroid Build Coastguard Worker   void Cancel();
78*6777b538SAndroid Build Coastguard Worker 
IsCancelled()79*6777b538SAndroid Build Coastguard Worker   bool IsCancelled() const { return state_ == State::kCancelled; }
80*6777b538SAndroid Build Coastguard Worker 
81*6777b538SAndroid Build Coastguard Worker   // Allows tests to inspect the current backoff/retry state.
82*6777b538SAndroid Build Coastguard Worker   const BackoffEntry& GetBackoffEntryForTesting() const;
83*6777b538SAndroid Build Coastguard Worker   const base::OneShotTimer& GetRetryTimerForTesting() const;
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker  protected:
86*6777b538SAndroid Build Coastguard Worker   // protected to allow sub-classing, but prevent deleting
87*6777b538SAndroid Build Coastguard Worker   virtual ~SerialWorker();
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker   // Create a new WorkItem to be passed to and run on the ThreadPool.
90*6777b538SAndroid Build Coastguard Worker   virtual std::unique_ptr<WorkItem> CreateWorkItem() = 0;
91*6777b538SAndroid Build Coastguard Worker 
92*6777b538SAndroid Build Coastguard Worker   // Executed on origin thread after `WorkItem` completes.
93*6777b538SAndroid Build Coastguard Worker   // Must return true on success.
94*6777b538SAndroid Build Coastguard Worker   virtual bool OnWorkFinished(std::unique_ptr<WorkItem> work_item) = 0;
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker   // Returns the failure count for this job.
97*6777b538SAndroid Build Coastguard Worker   int GetFailureCount() const;
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker   base::WeakPtr<SerialWorker> AsWeakPtr();
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker   // Used to verify that the constructor, WorkNow(), Cancel() and
102*6777b538SAndroid Build Coastguard Worker   // OnWorkJobFinished() are called on the same sequence.
103*6777b538SAndroid Build Coastguard Worker   SEQUENCE_CHECKER(sequence_checker_);
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker  private:
106*6777b538SAndroid Build Coastguard Worker   enum class State {
107*6777b538SAndroid Build Coastguard Worker     kCancelled = -1,
108*6777b538SAndroid Build Coastguard Worker     kIdle = 0,
109*6777b538SAndroid Build Coastguard Worker     kWorking,  // |DoWorkJob| posted to ThreadPool, until |OnWorkJobFinished|
110*6777b538SAndroid Build Coastguard Worker     kPending,  // |WorkNow| while WORKING, must re-do work
111*6777b538SAndroid Build Coastguard Worker   };
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker   void WorkNowInternal();
114*6777b538SAndroid Build Coastguard Worker 
115*6777b538SAndroid Build Coastguard Worker   // Called on the origin thread after `WorkItem::DoWork()` completes.
116*6777b538SAndroid Build Coastguard Worker   void OnDoWorkFinished(std::unique_ptr<WorkItem> work_item);
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   // Called on the origin thread after `WorkItem::FollowupWork()` completes.
119*6777b538SAndroid Build Coastguard Worker   void OnFollowupWorkFinished(std::unique_ptr<WorkItem> work_item);
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker   void RerunWork(std::unique_ptr<WorkItem> work_item);
122*6777b538SAndroid Build Coastguard Worker 
123*6777b538SAndroid Build Coastguard Worker   State state_ = State::kIdle;
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   // Max retries and backoff entry to control timing.
126*6777b538SAndroid Build Coastguard Worker   const int max_number_of_retries_;
127*6777b538SAndroid Build Coastguard Worker   BackoffEntry backoff_entry_;
128*6777b538SAndroid Build Coastguard Worker   base::OneShotTimer retry_timer_;
129*6777b538SAndroid Build Coastguard Worker 
130*6777b538SAndroid Build Coastguard Worker   base::WeakPtrFactory<SerialWorker> weak_factory_{this};
131*6777b538SAndroid Build Coastguard Worker };
132*6777b538SAndroid Build Coastguard Worker 
133*6777b538SAndroid Build Coastguard Worker }  // namespace net
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker #endif  // NET_DNS_SERIAL_WORKER_H_
136