chromium/base/functional/concurrent_callbacks.h

// 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_