1 // Copyright 2020 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.
5 #ifndef BASE_BIND_POST_TASK_INTERNAL_H_
6 #define BASE_BIND_POST_TASK_INTERNAL_H_
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/location.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/task_runner.h"
19 // Helper class to ensure that the input callback is always invoked and
20 // destroyed on the provided task runner.
21 template <typename CallbackType>
22 class BindPostTaskTrampoline {
24 BindPostTaskTrampoline(scoped_refptr<TaskRunner> task_runner,
25 const Location& location,
26 CallbackType callback)
27 : task_runner_(std::move(task_runner)),
29 callback_(std::move(callback)) {
31 // Crash immediately instead of when trying to Run() `callback_` on the
32 // destination `task_runner_`.
36 BindPostTaskTrampoline(const BindPostTaskTrampoline& other) = delete;
37 BindPostTaskTrampoline& operator=(const BindPostTaskTrampoline& other) =
40 ~BindPostTaskTrampoline() {
42 // Post a task to ensure that `callback_` is destroyed on `task_runner_`.
43 // The callback's BindState may own an object that isn't threadsafe and is
44 // unsafe to destroy on a different task runner.
46 // Note that while this guarantees `callback_` will be destroyed when the
47 // posted task runs, it doesn't guarantee the ref-counted BindState is
48 // destroyed at the same time. If the callback was copied before being
49 // passed to BindPostTaskTrampoline then the BindState can outlive
50 // `callback_`, so the user must ensure any other copies of the callback
51 // are also destroyed on the correct task runner.
52 task_runner_->PostTask(location_, BindOnce(&DestroyCallbackOnTaskRunner,
53 std::move(callback_)));
57 template <typename... Args>
58 void Run(Args... args) {
59 // If CallbackType is a OnceCallback then GetClosure() consumes `callback_`.
60 task_runner_->PostTask(location_,
61 GetClosure(&callback_, std::forward<Args>(args)...));
65 static OnceClosure GetClosure(OnceClosure* callback) {
66 // `callback` is already a closure, no need to call BindOnce().
67 return std::move(*callback);
70 template <typename... Args>
71 static OnceClosure GetClosure(OnceCallback<void(Args...)>* callback,
73 return BindOnce(std::move(*callback), std::forward<Args>(args)...);
76 static OnceClosure GetClosure(RepeatingClosure* callback) {
77 // `callback` is already a closure, no need to call BindOnce().
81 template <typename... Args>
82 static OnceClosure GetClosure(RepeatingCallback<void(Args...)>* callback,
84 return BindOnce(*callback, std::forward<Args>(args)...);
87 static void DestroyCallbackOnTaskRunner(CallbackType callback) {}
89 const scoped_refptr<TaskRunner> task_runner_;
90 const Location location_;
91 CallbackType callback_;
94 } // namespace internal
97 #endif // BASE_BIND_POST_TASK_INTERNAL_H_