// Copyright 2024 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_FUNCTIONAL_CONCURRENT_CALLBACKS_H_ #define BASE_FUNCTIONAL_CONCURRENT_CALLBACKS_H_ #include <memory> #include <type_traits> #include <vector> #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/location.h" #include "base/memory/raw_ptr.h" #include "base/sequence_checker.h" #include "base/task/bind_post_task.h" #include "base/task/sequenced_task_runner.h" // OVERVIEW: // // ConcurrentCallbacks<T> is an alternative to BarrierCallback<T>, it dispenses // OnceCallbacks via CreateCallback() and invokes the callback passed to Done() // after all prior callbacks have been run. // // ConcurrentCallbacks<T> is intended to be used over BarrierCallback<T> in // cases where the count is unknown prior to requiring a callback to start a // task, and for cases where the count is manually derived from the code and // subject to human error. // // IMPORTANT NOTES: // // - ConcurrentCallbacks<T> is NOT thread safe. // - The done callback will NOT be run synchronously, it will be PostTask() to // the sequence that Done() was invoked on. // - ConcurrentCallbacks<T> cannot be used after Done() is called, a CHECK // verifies this. // // TYPICAL USAGE: // // class Example { // void OnRequestsReceived(std::vector<Request> requests) { // base::ConcurrentCallbacks<Result> concurrent; // // for (Request& request : requests) { // if (IsValidRequest(request)) { // StartRequest(std::move(request), concurrent.CreateCallback()); // } // } // // std::move(concurrent).Done( // base::BindOnce(&Example::OnRequestsComplete, GetWeakPtr())); // } // // void StartRequest(Request request, // base::OnceCallback<void(Result)> callback) { // // Process the request asynchronously and call callback with a Result. // } // // void OnRequestsComplete(std::vector<Result> results) { // // Invoked after all requests are completed and receives the results of // // all of them. // } // }; namespace base { template <typename T> class ConcurrentCallbacks { … }; } // namespace base #endif // BASE_FUNCTIONAL_CONCURRENT_CALLBACKS_H_