1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
// 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_
|