xref: /aosp_15_r20/external/cronet/base/task/bind_post_task.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TASK_BIND_POST_TASK_H_
6 #define BASE_TASK_BIND_POST_TASK_H_
7 
8 #include <memory>
9 #include <type_traits>
10 #include <utility>
11 
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/location.h"
15 #include "base/task/bind_post_task_internal.h"
16 #include "base/task/sequenced_task_runner.h"
17 #include "base/task/task_runner.h"
18 
19 // BindPostTask() is a helper function for binding a OnceCallback or
20 // RepeatingCallback to a task runner. BindPostTask(task_runner, callback)
21 // returns a task runner bound callback with an identical type to |callback|.
22 // The returned callback will take the same arguments as the input |callback|.
23 // Invoking Run() on the returned callback will post a task to run |callback| on
24 // target |task_runner| with the provided arguments.
25 //
26 // This is typically used when a callback must be invoked on a specific task
27 // runner but is provided as a result callback to a function that runs
28 // asynchronously on a different task runner.
29 //
30 // Example:
31 //    // |result_cb| can only be safely run on |my_task_runner|.
32 //    auto result_cb = BindOnce(&Foo::ReceiveReply, foo);
33 //    // Note that even if |returned_cb| is never run |result_cb| will attempt
34 //    // to be destroyed on |my_task_runner|.
35 //    auto returned_cb = BindPostTask(my_task_runner, std::move(result_cb));
36 //    // RunAsyncTask() will run the provided callback upon completion.
37 //    other_task_runner->PostTask(FROM_HERE,
38 //                                BindOnce(&RunAsyncTask,
39 //                                         std::move(returned_cb)));
40 //
41 // If the example provided |result_cb| to RunAsyncTask() then |result_cb| would
42 // run unsafely on |other_task_runner|. Instead RunAsyncTask() will run
43 // |returned_cb| which will post a task to |current_task_runner| before running
44 // |result_cb| safely.
45 //
46 // An alternative approach in the example above is to change RunAsyncTask() to
47 // also take a task runner as an argument and have RunAsyncTask() post the task.
48 // For cases where that isn't desirable BindPostTask() provides a convenient
49 // alternative.
50 //
51 // The input |callback| will always attempt to be destroyed on the target task
52 // runner. Even if the returned callback is never invoked, a task will be posted
53 // to destroy the input |callback|. However, if the target task runner has
54 // shutdown this is no longer possible. PostTask() will return false and the
55 // callback will be destroyed immediately on the current thread.
56 //
57 // The input |callback| must have a void return type to be compatible with
58 // PostTask(). If you want to drop the callback return value then use
59 // base::IgnoreResult(&Func) when creating the input |callback|.
60 
61 namespace base {
62 
63 // Creates a OnceCallback that will run |callback| on |task_runner|. If the
64 // returned callback is destroyed without being run then |callback| will be
65 // be destroyed on |task_runner|.
66 template <typename ReturnType, typename... Args>
67   requires std::is_void_v<ReturnType>
68 OnceCallback<void(Args...)> BindPostTask(
69     scoped_refptr<TaskRunner> task_runner,
70     OnceCallback<ReturnType(Args...)> callback,
71     const Location& location = FROM_HERE) {
72   using Helper = internal::BindPostTaskTrampoline<OnceCallback<void(Args...)>>;
73 
74   return base::BindOnce(
75       &Helper::template Run<Args...>,
76       std::make_unique<Helper>(std::move(task_runner), location,
77                                std::move(callback)));
78 }
79 
80 // Creates a RepeatingCallback that will run |callback| on |task_runner|. When
81 // the returned callback is destroyed a task will be posted to destroy the input
82 // |callback| on |task_runner|.
83 template <typename ReturnType, typename... Args>
84   requires std::is_void_v<ReturnType>
85 RepeatingCallback<void(Args...)> BindPostTask(
86     scoped_refptr<TaskRunner> task_runner,
87     RepeatingCallback<ReturnType(Args...)> callback,
88     const Location& location = FROM_HERE) {
89   using Helper =
90       internal::BindPostTaskTrampoline<RepeatingCallback<void(Args...)>>;
91 
92   return base::BindRepeating(
93       &Helper::template Run<Args...>,
94       std::make_unique<Helper>(std::move(task_runner), location,
95                                std::move(callback)));
96 }
97 
98 // Creates a OnceCallback or RepeatingCallback that will run the `callback` on
99 // the default SequencedTaskRunner for the current sequence, i.e.
100 // `SequencedTaskRunner::GetCurrentDefault()`.
101 // Notes:
102 // - Please prefer using `base::SequenceBound<T>` if applicable.
103 // - Please consider using `base::PostTaskAndReplyWithResult()` instead where
104 // appropriate.
105 // - Please consider using an explicit task runner.
106 // - Only use this helper as a last resort if none of the above apply.
107 
108 template <typename ReturnType, typename... Args>
109   requires std::is_void_v<ReturnType>
110 OnceCallback<void(Args...)> BindPostTaskToCurrentDefault(
111     OnceCallback<ReturnType(Args...)> callback,
112     const Location& location = FROM_HERE) {
113   return BindPostTask(SequencedTaskRunner::GetCurrentDefault(),
114                       std::move(callback), location);
115 }
116 
117 template <typename ReturnType, typename... Args>
118   requires std::is_void_v<ReturnType>
119 RepeatingCallback<void(Args...)> BindPostTaskToCurrentDefault(
120     RepeatingCallback<ReturnType(Args...)> callback,
121     const Location& location = FROM_HERE) {
122   return BindPostTask(SequencedTaskRunner::GetCurrentDefault(),
123                       std::move(callback), location);
124 }
125 
126 }  // namespace base
127 
128 #endif  // BASE_TASK_BIND_POST_TASK_H_
129