|  | // Copyright 2020 The Chromium Authors | 
|  | // 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_H_ | 
|  | #define BASE_TASK_BIND_POST_TASK_H_ | 
|  |  | 
|  | #include <memory> | 
|  | #include <type_traits> | 
|  | #include <utility> | 
|  |  | 
|  | #include "base/functional/bind.h" | 
|  | #include "base/functional/callback.h" | 
|  | #include "base/location.h" | 
|  | #include "base/task/bind_post_task_internal.h" | 
|  | #include "base/task/sequenced_task_runner.h" | 
|  | #include "base/task/task_runner.h" | 
|  |  | 
|  | // BindPostTask() is a helper function for binding a OnceCallback or | 
|  | // RepeatingCallback to a task runner. BindPostTask(task_runner, callback) | 
|  | // returns a task runner bound callback with an identical type to |callback|. | 
|  | // The returned callback will take the same arguments as the input |callback|. | 
|  | // Invoking Run() on the returned callback will post a task to run |callback| on | 
|  | // target |task_runner| with the provided arguments. | 
|  | // | 
|  | // This is typically used when a callback must be invoked on a specific task | 
|  | // runner but is provided as a result callback to a function that runs | 
|  | // asynchronously on a different task runner. | 
|  | // | 
|  | // Example: | 
|  | //    // |result_cb| can only be safely run on |my_task_runner|. | 
|  | //    auto result_cb = BindOnce(&Foo::ReceiveReply, foo); | 
|  | //    // Note that even if |returned_cb| is never run |result_cb| will attempt | 
|  | //    // to be destroyed on |my_task_runner|. | 
|  | //    auto returned_cb = BindPostTask(my_task_runner, std::move(result_cb)); | 
|  | //    // RunAsyncTask() will run the provided callback upon completion. | 
|  | //    other_task_runner->PostTask(FROM_HERE, | 
|  | //                                BindOnce(&RunAsyncTask, | 
|  | //                                         std::move(returned_cb))); | 
|  | // | 
|  | // If the example provided |result_cb| to RunAsyncTask() then |result_cb| would | 
|  | // run unsafely on |other_task_runner|. Instead RunAsyncTask() will run | 
|  | // |returned_cb| which will post a task to |current_task_runner| before running | 
|  | // |result_cb| safely. | 
|  | // | 
|  | // An alternative approach in the example above is to change RunAsyncTask() to | 
|  | // also take a task runner as an argument and have RunAsyncTask() post the task. | 
|  | // For cases where that isn't desirable BindPostTask() provides a convenient | 
|  | // alternative. | 
|  | // | 
|  | // The input |callback| will always attempt to be destroyed on the target task | 
|  | // runner. Even if the returned callback is never invoked, a task will be posted | 
|  | // to destroy the input |callback|. However, if the target task runner has | 
|  | // shutdown this is no longer possible. PostTask() will return false and the | 
|  | // callback will be destroyed immediately on the current thread. | 
|  | // | 
|  | // The input |callback| must have a void return type to be compatible with | 
|  | // PostTask(). If you want to drop the callback return value then use | 
|  | // base::IgnoreResult(&Func) when creating the input |callback|. | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | // Creates a OnceCallback that will run |callback| on |task_runner|. If the | 
|  | // returned callback is destroyed without being run then |callback| will be | 
|  | // be destroyed on |task_runner|. | 
|  | template <typename ReturnType, typename... Args> | 
|  | requires std::is_void_v<ReturnType> | 
|  | OnceCallback<void(Args...)> BindPostTask( | 
|  | scoped_refptr<TaskRunner> task_runner, | 
|  | OnceCallback<ReturnType(Args...)> callback, | 
|  | const Location& location = FROM_HERE) { | 
|  | using Helper = internal::BindPostTaskTrampoline<OnceCallback<void(Args...)>>; | 
|  |  | 
|  | return base::BindOnce( | 
|  | &Helper::template Run<Args...>, | 
|  | std::make_unique<Helper>(std::move(task_runner), location, | 
|  | std::move(callback))); | 
|  | } | 
|  |  | 
|  | // Creates a RepeatingCallback that will run |callback| on |task_runner|. When | 
|  | // the returned callback is destroyed a task will be posted to destroy the input | 
|  | // |callback| on |task_runner|. | 
|  | template <typename ReturnType, typename... Args> | 
|  | requires std::is_void_v<ReturnType> | 
|  | RepeatingCallback<void(Args...)> BindPostTask( | 
|  | scoped_refptr<TaskRunner> task_runner, | 
|  | RepeatingCallback<ReturnType(Args...)> callback, | 
|  | const Location& location = FROM_HERE) { | 
|  | using Helper = | 
|  | internal::BindPostTaskTrampoline<RepeatingCallback<void(Args...)>>; | 
|  |  | 
|  | return base::BindRepeating( | 
|  | &Helper::template Run<Args...>, | 
|  | std::make_unique<Helper>(std::move(task_runner), location, | 
|  | std::move(callback))); | 
|  | } | 
|  |  | 
|  | // Creates a OnceCallback or RepeatingCallback that will run the `callback` on | 
|  | // the default SequencedTaskRunner for the current sequence, i.e. | 
|  | // `SequencedTaskRunner::GetCurrentDefault()`. | 
|  | // Notes: | 
|  | // - Please prefer using `base::SequenceBound<T>` if applicable. | 
|  | // - Please consider using `base::PostTaskAndReplyWithResult()` instead where | 
|  | // appropriate. | 
|  | // - Please consider using an explicit task runner. | 
|  | // - Only use this helper as a last resort if none of the above apply. | 
|  |  | 
|  | template <typename ReturnType, typename... Args> | 
|  | requires std::is_void_v<ReturnType> | 
|  | OnceCallback<void(Args...)> BindPostTaskToCurrentDefault( | 
|  | OnceCallback<ReturnType(Args...)> callback, | 
|  | const Location& location = FROM_HERE) { | 
|  | return BindPostTask(SequencedTaskRunner::GetCurrentDefault(), | 
|  | std::move(callback), location); | 
|  | } | 
|  |  | 
|  | template <typename ReturnType, typename... Args> | 
|  | requires std::is_void_v<ReturnType> | 
|  | RepeatingCallback<void(Args...)> BindPostTaskToCurrentDefault( | 
|  | RepeatingCallback<ReturnType(Args...)> callback, | 
|  | const Location& location = FROM_HERE) { | 
|  | return BindPostTask(SequencedTaskRunner::GetCurrentDefault(), | 
|  | std::move(callback), location); | 
|  | } | 
|  |  | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_TASK_BIND_POST_TASK_H_ |