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