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