xref: /aosp_15_r20/external/cronet/base/critical_closure.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 BASE_CRITICAL_CLOSURE_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_CRITICAL_CLOSURE_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <string_view>
9*6777b538SAndroid Build Coastguard Worker #include <utility>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
13*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
14*6777b538SAndroid Build Coastguard Worker #include "build/ios_buildflags.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_APP_EXTENSION)
17*6777b538SAndroid Build Coastguard Worker #include <optional>
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/ios/scoped_critical_action.h"
21*6777b538SAndroid Build Coastguard Worker #endif
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker namespace base {
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker namespace internal {
26*6777b538SAndroid Build Coastguard Worker 
27*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_APP_EXTENSION)
28*6777b538SAndroid Build Coastguard Worker // This class wraps a closure so it can continue to run for a period of time
29*6777b538SAndroid Build Coastguard Worker // when the application goes to the background by using
30*6777b538SAndroid Build Coastguard Worker // |ios::ScopedCriticalAction|.
31*6777b538SAndroid Build Coastguard Worker class ImmediateCriticalClosure {
32*6777b538SAndroid Build Coastguard Worker  public:
33*6777b538SAndroid Build Coastguard Worker   explicit ImmediateCriticalClosure(std::string_view task_name,
34*6777b538SAndroid Build Coastguard Worker                                     OnceClosure closure);
35*6777b538SAndroid Build Coastguard Worker   ImmediateCriticalClosure(const ImmediateCriticalClosure&) = delete;
36*6777b538SAndroid Build Coastguard Worker   ImmediateCriticalClosure& operator=(const ImmediateCriticalClosure&) = delete;
37*6777b538SAndroid Build Coastguard Worker   ~ImmediateCriticalClosure();
38*6777b538SAndroid Build Coastguard Worker   void Run();
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker  private:
41*6777b538SAndroid Build Coastguard Worker   ios::ScopedCriticalAction critical_action_;
42*6777b538SAndroid Build Coastguard Worker   OnceClosure closure_;
43*6777b538SAndroid Build Coastguard Worker };
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker // This class is identical to ImmediateCriticalClosure, but the critical action
46*6777b538SAndroid Build Coastguard Worker // is started when the action runs, not when the CriticalAction is created.
47*6777b538SAndroid Build Coastguard Worker class PendingCriticalClosure {
48*6777b538SAndroid Build Coastguard Worker  public:
49*6777b538SAndroid Build Coastguard Worker   explicit PendingCriticalClosure(std::string_view task_name,
50*6777b538SAndroid Build Coastguard Worker                                   OnceClosure closure);
51*6777b538SAndroid Build Coastguard Worker   PendingCriticalClosure(const PendingCriticalClosure&) = delete;
52*6777b538SAndroid Build Coastguard Worker   PendingCriticalClosure& operator=(const PendingCriticalClosure&) = delete;
53*6777b538SAndroid Build Coastguard Worker   ~PendingCriticalClosure();
54*6777b538SAndroid Build Coastguard Worker   void Run();
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker  private:
57*6777b538SAndroid Build Coastguard Worker   std::optional<ios::ScopedCriticalAction> critical_action_;
58*6777b538SAndroid Build Coastguard Worker   std::string task_name_;
59*6777b538SAndroid Build Coastguard Worker   OnceClosure closure_;
60*6777b538SAndroid Build Coastguard Worker };
61*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_IOS)
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker }  // namespace internal
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker // Returns a closure that will continue to run for a period of time when the
66*6777b538SAndroid Build Coastguard Worker // application goes to the background if possible on platforms where
67*6777b538SAndroid Build Coastguard Worker // applications don't execute while backgrounded, otherwise the original task is
68*6777b538SAndroid Build Coastguard Worker // returned. If |is_immediate| is true, the closure will immediately prevent
69*6777b538SAndroid Build Coastguard Worker // background suspension. Otherwise, the closure will wait to request background
70*6777b538SAndroid Build Coastguard Worker // permission until it is run.
71*6777b538SAndroid Build Coastguard Worker //
72*6777b538SAndroid Build Coastguard Worker // Example:
73*6777b538SAndroid Build Coastguard Worker //   file_task_runner_->PostTask(
74*6777b538SAndroid Build Coastguard Worker //       FROM_HERE,
75*6777b538SAndroid Build Coastguard Worker //       MakeCriticalClosure(task_name,
76*6777b538SAndroid Build Coastguard Worker //                           base::BindOnce(&WriteToDiskTask, path_, data)));
77*6777b538SAndroid Build Coastguard Worker //
78*6777b538SAndroid Build Coastguard Worker // Note new closures might be posted in this closure. If the new closures need
79*6777b538SAndroid Build Coastguard Worker // background running time, |MakeCriticalClosure| should be applied on them
80*6777b538SAndroid Build Coastguard Worker // before posting. |task_name| is used by the platform to identify any tasks
81*6777b538SAndroid Build Coastguard Worker // that do not complete in time for suspension.
82*6777b538SAndroid Build Coastguard Worker //
83*6777b538SAndroid Build Coastguard Worker // This function is used automatically for tasks posted to a sequence runner
84*6777b538SAndroid Build Coastguard Worker // using TaskShutdownBehavior::BLOCK_SHUTDOWN.
85*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_APP_EXTENSION)
MakeCriticalClosure(std::string_view task_name,OnceClosure closure,bool is_immediate)86*6777b538SAndroid Build Coastguard Worker inline OnceClosure MakeCriticalClosure(std::string_view task_name,
87*6777b538SAndroid Build Coastguard Worker                                        OnceClosure closure,
88*6777b538SAndroid Build Coastguard Worker                                        bool is_immediate) {
89*6777b538SAndroid Build Coastguard Worker   // Wrapping a null closure in a critical closure has unclear semantics and
90*6777b538SAndroid Build Coastguard Worker   // most likely indicates a bug. CHECK-ing early allows detecting and
91*6777b538SAndroid Build Coastguard Worker   // investigating these cases more easily.
92*6777b538SAndroid Build Coastguard Worker   CHECK(!closure.is_null());
93*6777b538SAndroid Build Coastguard Worker   if (is_immediate) {
94*6777b538SAndroid Build Coastguard Worker     return base::BindOnce(&internal::ImmediateCriticalClosure::Run,
95*6777b538SAndroid Build Coastguard Worker                           Owned(new internal::ImmediateCriticalClosure(
96*6777b538SAndroid Build Coastguard Worker                               task_name, std::move(closure))));
97*6777b538SAndroid Build Coastguard Worker   } else {
98*6777b538SAndroid Build Coastguard Worker     return base::BindOnce(&internal::PendingCriticalClosure::Run,
99*6777b538SAndroid Build Coastguard Worker                           Owned(new internal::PendingCriticalClosure(
100*6777b538SAndroid Build Coastguard Worker                               task_name, std::move(closure))));
101*6777b538SAndroid Build Coastguard Worker   }
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker 
MakeCriticalClosure(const Location & posted_from,OnceClosure closure,bool is_immediate)104*6777b538SAndroid Build Coastguard Worker inline OnceClosure MakeCriticalClosure(const Location& posted_from,
105*6777b538SAndroid Build Coastguard Worker                                        OnceClosure closure,
106*6777b538SAndroid Build Coastguard Worker                                        bool is_immediate) {
107*6777b538SAndroid Build Coastguard Worker   return MakeCriticalClosure(posted_from.ToString(), std::move(closure),
108*6777b538SAndroid Build Coastguard Worker                              is_immediate);
109*6777b538SAndroid Build Coastguard Worker }
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker #else  // BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_APP_EXTENSION)
112*6777b538SAndroid Build Coastguard Worker 
MakeCriticalClosure(std::string_view task_name,OnceClosure closure,bool is_immediate)113*6777b538SAndroid Build Coastguard Worker inline OnceClosure MakeCriticalClosure(std::string_view task_name,
114*6777b538SAndroid Build Coastguard Worker                                        OnceClosure closure,
115*6777b538SAndroid Build Coastguard Worker                                        bool is_immediate) {
116*6777b538SAndroid Build Coastguard Worker   // No-op for platforms where the application does not need to acquire
117*6777b538SAndroid Build Coastguard Worker   // background time for closures to finish when it goes into the background.
118*6777b538SAndroid Build Coastguard Worker   return closure;
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker 
MakeCriticalClosure(const Location & posted_from,OnceClosure closure,bool is_immediate)121*6777b538SAndroid Build Coastguard Worker inline OnceClosure MakeCriticalClosure(const Location& posted_from,
122*6777b538SAndroid Build Coastguard Worker                                        OnceClosure closure,
123*6777b538SAndroid Build Coastguard Worker                                        bool is_immediate) {
124*6777b538SAndroid Build Coastguard Worker   return closure;
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_APP_EXTENSION)
128*6777b538SAndroid Build Coastguard Worker 
129*6777b538SAndroid Build Coastguard Worker }  // namespace base
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker #endif  // BASE_CRITICAL_CLOSURE_H_
132