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
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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 <utility>
#include "base/callback.h"
#include "base/location.h"
#include "base/strings/string_piece.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_IOS)
#include "base/bind.h"
#include "base/ios/scoped_critical_action.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#endif
namespace base {
namespace internal {
#if BUILDFLAG(IS_IOS)
// 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(StringPiece 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(StringPiece task_name, OnceClosure closure);
PendingCriticalClosure(const PendingCriticalClosure&) = delete;
PendingCriticalClosure& operator=(const PendingCriticalClosure&) = delete;
~PendingCriticalClosure();
void Run();
private:
absl::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.
#if BUILDFLAG(IS_IOS)
inline OnceClosure MakeCriticalClosure(StringPiece task_name,
OnceClosure closure,
bool is_immediate) {
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)
inline OnceClosure MakeCriticalClosure(StringPiece 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)
} // namespace base
#endif // BASE_CRITICAL_CLOSURE_H_
|