blob: d06524609fc278b7bc53c7e88afce88764b79652 [file] [log] [blame]
Alan Cutter990ac5ac2023-03-01 03:20:491// Copyright 2023 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 CHROME_BROWSER_WEB_APPLICATIONS_CALLBACK_UTILS_H_
6#define CHROME_BROWSER_WEB_APPLICATIONS_CALLBACK_UTILS_H_
7
8#include "base/functional/callback.h"
Andrew Rayskiy82393422024-10-22 15:34:489#include "base/memory/weak_ptr.h"
Alan Cutter990ac5ac2023-03-01 03:20:4910
11namespace web_app {
12
13// RunChainedCallbacks() runs multiple callbacks chained together by
14// successively binding the final callback as parameter to the one before it
15// until the entire sequence has been bound together.
16//
17// Example usage:
18//
19// class CounterStorage {
20// public:
21// void AddToCounter(size_t value, base::OnceClosure callback) {
22// auto weak_ptr = weak_ptr_factory_.GetWeakPtr();
23// RunChainedCallbacks(
24// base::BindOnce(&CounterStorage::AcquireFileLock, weak_ptr),
25// base::BindOnce(&CounterStorage::StashFileLock, weak_ptr),
26// base::BindOnce(&CounterStorage::ReadCounter, weak_ptr),
27// base::BindOnce(&CounterStorage::Add, weak_ptr, value),
28// base::BindOnce(&CounterStorage::WriteCounter, weak_ptr),
29// base::BindOnce(&CounterStorage::ReleaseFileLock, weak_ptr),
30// std::move(callback));
31// }
32//
33// private:
34// void AcquireFileLock(
35// base::OnceCallback<void(FileLock)> next_step_callback);
36// void StashFileLock(base::OnceClosure next_step_callback, FileLock lock);
37// void ReadCounter(base::OnceCallback<void(size_t)> next_step_callback);
38// void Add(size_t value,
39// base::OnceCallback<void(size_t)> next_step_callback,
40// size_t count);
41// void WriteCounter(base::OnceClosure next_step_callback, size_t count);
42// void ReleaseFileLock(base::OnceClosure next_step_callback);
43//
Arthur Sonzognife132ee2024-01-15 11:01:0444// std::optional<FileLock> lock_;
Alan Cutter990ac5ac2023-03-01 03:20:4945// base::WeakPtrFactory<CounterStorage> weak_ptr_factory_{this};
46// };
47//
48// The alternate way to write AddLog() without RunChainedCallbacks() would be:
49// base::BindOnce(
50// &Logger::AcquireFileLock,
51// weak_ptr,
52// base::BindOnce(
53// &Logger::StashFileLock,
54// weak_ptr,
55// base::BindOnce(
56// &Logger::ReadCounter,
57// weak_ptr,
58// base::BindOnce(
59// &Logger::Add,
60// weak_ptr,
61// value,
62// base::BindOnce(&Logger::WriteCounter,
63// weak_ptr,
64// base::BindOnce(&Logger::ReleaseFileLock,
65// weak_ptr,
66// std::move(callback)))))));
67//
68// RunChainedCallbacks() allows writing single action async methods that don't
69// need to know about the high level procedure while avoiding messy indented
70// nesting of multiple base::BindOnce() calls.
71
72template <typename Callback>
73Callback ChainCallbacks(Callback&& callback) {
74 return std::forward<Callback>(callback);
75}
76
77template <typename FirstCallback, typename... NextCallbacks>
78decltype(auto) ChainCallbacks(FirstCallback&& first_callback,
79 NextCallbacks&&... next_callbacks) {
80 return base::BindOnce(std::forward<FirstCallback>(first_callback),
81 ChainCallbacks<NextCallbacks...>(
82 std::forward<NextCallbacks>(next_callbacks)...));
83}
84
85template <typename... Callbacks>
86decltype(auto) RunChainedCallbacks(Callbacks&&... callbacks) {
87 return ChainCallbacks(std::forward<Callbacks>(callbacks)...).Run();
88}
89
Andrew Rayskiy82393422024-10-22 15:34:4890template <typename T, typename... Funcs>
91decltype(auto) RunChainedWeakCallbacks(base::WeakPtr<T> weak_ptr,
92 Funcs... funcs) {
93 return RunChainedCallbacks(base::BindOnce(funcs, weak_ptr)...);
94}
95
Alan Cutter990ac5ac2023-03-01 03:20:4996} // namespace web_app
97
98#endif // CHROME_BROWSER_WEB_APPLICATIONS_CALLBACK_UTILS_H_