135 lines
5.8 KiB
C++
135 lines
5.8 KiB
C++
// 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>
|
|
OnceCallback<void(Args...)> BindPostTask(
|
|
scoped_refptr<TaskRunner> task_runner,
|
|
OnceCallback<ReturnType(Args...)> callback,
|
|
const Location& location = FROM_HERE) {
|
|
static_assert(std::is_same<ReturnType, void>::value,
|
|
"OnceCallback must have void return type in order to produce a "
|
|
"closure for PostTask(). Use base::IgnoreResult() to drop the "
|
|
"return value if desired.");
|
|
|
|
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>
|
|
RepeatingCallback<void(Args...)> BindPostTask(
|
|
scoped_refptr<TaskRunner> task_runner,
|
|
RepeatingCallback<ReturnType(Args...)> callback,
|
|
const Location& location = FROM_HERE) {
|
|
static_assert(std::is_same<ReturnType, void>::value,
|
|
"RepeatingCallback must have void return type in order to "
|
|
"produce a closure for PostTask(). Use base::IgnoreResult() to "
|
|
"drop the return value if desired.");
|
|
|
|
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>
|
|
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>
|
|
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_
|