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