1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be
3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file.
4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#ifndef BASE_CRITICAL_CLOSURE_H_
6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define BASE_CRITICAL_CLOSURE_H_
7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/callback.h"
9cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "base/macros.h"
10cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "build/build_config.h"
11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_IOS)
13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/bind.h"
14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/ios/scoped_critical_action.h"
15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif
16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base {
18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace internal {
20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_IOS)
22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Returns true if multi-tasking is supported on this iOS device.
23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool IsMultiTaskingSupported();
24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This class wraps a closure so it can continue to run for a period of time
26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// when the application goes to the background by using
27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// |ios::ScopedCriticalAction|.
28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate <typename R>
29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass CriticalClosure {
30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  explicit CriticalClosure(const Callback<R(void)>& closure)
32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      : closure_(closure) {}
33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ~CriticalClosure() {}
35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  R Run() {
37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return closure_.Run();
38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ios::ScopedCriticalAction critical_action_;
42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Callback<R(void)> closure_;
43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DISALLOW_COPY_AND_ASSIGN(CriticalClosure);
45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif  // defined(OS_IOS)
47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace internal
49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Returns a closure (which may return a result, but must not require any extra
51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// arguments) that will continue to run for a period of time when the
52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// application goes to the background if possible on platforms where
53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// applications don't execute while backgrounded, otherwise the original task is
54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// returned.
55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//
56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Example:
57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//   file_task_runner_->PostTask(
58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//       FROM_HERE,
59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//       MakeCriticalClosure(base::Bind(&WriteToDiskTask, path_, data)));
60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//
61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Note new closures might be posted in this closure. If the new closures need
62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// background running time, |MakeCriticalClosure| should be applied on them
63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// before posting.
64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_IOS)
65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate <typename R>
66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratCallback<R(void)> MakeCriticalClosure(const Callback<R(void)>& closure) {
67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(internal::IsMultiTaskingSupported());
68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return base::Bind(&internal::CriticalClosure<R>::Run,
69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                    Owned(new internal::CriticalClosure<R>(closure)));
70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else  // defined(OS_IOS)
72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate <typename R>
73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Callback<R(void)> MakeCriticalClosure(const Callback<R(void)>& closure) {
74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // No-op for platforms where the application does not need to acquire
75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // background time for closures to finish when it goes into the background.
76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return closure;
77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif  // defined(OS_IOS)
79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace base
81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif  // BASE_CRITICAL_CLOSURE_H_
83