critical_closure.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_CRITICAL_CLOSURE_H_
  5. #define BASE_CRITICAL_CLOSURE_H_
  6. #include <utility>
  7. #include "base/callback.h"
  8. #include "base/location.h"
  9. #include "base/strings/string_piece.h"
  10. #include "build/build_config.h"
  11. #if BUILDFLAG(IS_IOS)
  12. #include "base/bind.h"
  13. #include "base/ios/scoped_critical_action.h"
  14. #include "third_party/abseil-cpp/absl/types/optional.h"
  15. #endif
  16. namespace base {
  17. namespace internal {
  18. #if BUILDFLAG(IS_IOS)
  19. // This class wraps a closure so it can continue to run for a period of time
  20. // when the application goes to the background by using
  21. // |ios::ScopedCriticalAction|.
  22. class ImmediateCriticalClosure {
  23. public:
  24. explicit ImmediateCriticalClosure(StringPiece task_name, OnceClosure closure);
  25. ImmediateCriticalClosure(const ImmediateCriticalClosure&) = delete;
  26. ImmediateCriticalClosure& operator=(const ImmediateCriticalClosure&) = delete;
  27. ~ImmediateCriticalClosure();
  28. void Run();
  29. private:
  30. ios::ScopedCriticalAction critical_action_;
  31. OnceClosure closure_;
  32. };
  33. // This class is identical to ImmediateCriticalClosure, but the critical action
  34. // is started when the action runs, not when the CriticalAction is created.
  35. class PendingCriticalClosure {
  36. public:
  37. explicit PendingCriticalClosure(StringPiece task_name, OnceClosure closure);
  38. PendingCriticalClosure(const PendingCriticalClosure&) = delete;
  39. PendingCriticalClosure& operator=(const PendingCriticalClosure&) = delete;
  40. ~PendingCriticalClosure();
  41. void Run();
  42. private:
  43. absl::optional<ios::ScopedCriticalAction> critical_action_;
  44. std::string task_name_;
  45. OnceClosure closure_;
  46. };
  47. #endif // BUILDFLAG(IS_IOS)
  48. } // namespace internal
  49. // Returns a closure that will continue to run for a period of time when the
  50. // application goes to the background if possible on platforms where
  51. // applications don't execute while backgrounded, otherwise the original task is
  52. // returned. If |is_immediate| is true, the closure will immediately prevent
  53. // background suspension. Otherwise, the closure will wait to request background
  54. // permission until it is run.
  55. //
  56. // Example:
  57. // file_task_runner_->PostTask(
  58. // FROM_HERE,
  59. // MakeCriticalClosure(task_name,
  60. // base::BindOnce(&WriteToDiskTask, path_, data)));
  61. //
  62. // Note new closures might be posted in this closure. If the new closures need
  63. // background running time, |MakeCriticalClosure| should be applied on them
  64. // before posting. |task_name| is used by the platform to identify any tasks
  65. // that do not complete in time for suspension.
  66. #if BUILDFLAG(IS_IOS)
  67. inline OnceClosure MakeCriticalClosure(StringPiece task_name,
  68. OnceClosure closure,
  69. bool is_immediate) {
  70. if (is_immediate) {
  71. return base::BindOnce(&internal::ImmediateCriticalClosure::Run,
  72. Owned(new internal::ImmediateCriticalClosure(
  73. task_name, std::move(closure))));
  74. } else {
  75. return base::BindOnce(&internal::PendingCriticalClosure::Run,
  76. Owned(new internal::PendingCriticalClosure(
  77. task_name, std::move(closure))));
  78. }
  79. }
  80. inline OnceClosure MakeCriticalClosure(const Location& posted_from,
  81. OnceClosure closure,
  82. bool is_immediate) {
  83. return MakeCriticalClosure(posted_from.ToString(), std::move(closure),
  84. is_immediate);
  85. }
  86. #else // BUILDFLAG(IS_IOS)
  87. inline OnceClosure MakeCriticalClosure(StringPiece task_name,
  88. OnceClosure closure,
  89. bool is_immediate) {
  90. // No-op for platforms where the application does not need to acquire
  91. // background time for closures to finish when it goes into the background.
  92. return closure;
  93. }
  94. inline OnceClosure MakeCriticalClosure(const Location& posted_from,
  95. OnceClosure closure,
  96. bool is_immediate) {
  97. return closure;
  98. }
  99. #endif // BUILDFLAG(IS_IOS)
  100. } // namespace base
  101. #endif // BASE_CRITICAL_CLOSURE_H_