12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- // Copyright 2020 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_TASK_BIND_POST_TASK_INTERNAL_H_
- #define BASE_TASK_BIND_POST_TASK_INTERNAL_H_
- #include <utility>
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/check.h"
- #include "base/location.h"
- #include "base/task/task_runner.h"
- namespace base {
- namespace internal {
- // Helper class to ensure that the input callback is always invoked and
- // destroyed on the provided task runner.
- template <typename CallbackType>
- class BindPostTaskTrampoline {
- public:
- BindPostTaskTrampoline(scoped_refptr<TaskRunner> task_runner,
- const Location& location,
- CallbackType callback)
- : task_runner_(std::move(task_runner)),
- location_(location),
- callback_(std::move(callback)) {
- DCHECK(task_runner_);
- // Crash immediately instead of when trying to Run() `callback_` on the
- // destination `task_runner_`.
- CHECK(callback_);
- }
- BindPostTaskTrampoline(const BindPostTaskTrampoline& other) = delete;
- BindPostTaskTrampoline& operator=(const BindPostTaskTrampoline& other) =
- delete;
- ~BindPostTaskTrampoline() {
- if (callback_) {
- // Post a task to ensure that `callback_` is destroyed on `task_runner_`.
- // The callback's BindState may own an object that isn't threadsafe and is
- // unsafe to destroy on a different task runner.
- //
- // Note that while this guarantees `callback_` will be destroyed when the
- // posted task runs, it doesn't guarantee the ref-counted BindState is
- // destroyed at the same time. If the callback was copied before being
- // passed to BindPostTaskTrampoline then the BindState can outlive
- // `callback_`, so the user must ensure any other copies of the callback
- // are also destroyed on the correct task runner.
- task_runner_->PostTask(location_, BindOnce(&DestroyCallbackOnTaskRunner,
- std::move(callback_)));
- }
- }
- template <typename... Args>
- void Run(Args... args) {
- // If CallbackType is a OnceCallback then GetClosure() consumes `callback_`.
- task_runner_->PostTask(location_,
- GetClosure(&callback_, std::forward<Args>(args)...));
- }
- private:
- static OnceClosure GetClosure(OnceClosure* callback) {
- // `callback` is already a closure, no need to call BindOnce().
- return std::move(*callback);
- }
- template <typename... Args>
- static OnceClosure GetClosure(OnceCallback<void(Args...)>* callback,
- Args&&... args) {
- return BindOnce(std::move(*callback), std::forward<Args>(args)...);
- }
- static OnceClosure GetClosure(RepeatingClosure* callback) {
- // `callback` is already a closure, no need to call BindOnce().
- return *callback;
- }
- template <typename... Args>
- static OnceClosure GetClosure(RepeatingCallback<void(Args...)>* callback,
- Args&&... args) {
- return BindOnce(*callback, std::forward<Args>(args)...);
- }
- static void DestroyCallbackOnTaskRunner(CallbackType callback) {}
- const scoped_refptr<TaskRunner> task_runner_;
- const Location location_;
- CallbackType callback_;
- };
- } // namespace internal
- } // namespace base
- #endif // BASE_TASK_BIND_POST_TASK_INTERNAL_H_
|