1 // Copyright 2024 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_FUNCTIONAL_CONCURRENT_CLOSURES_H_ 6 #define BASE_FUNCTIONAL_CONCURRENT_CLOSURES_H_ 7 8 #include "base/base_export.h" 9 #include "base/functional/callback.h" 10 #include "base/location.h" 11 #include "base/memory/raw_ptr.h" 12 #include "base/sequence_checker.h" 13 #include "base/task/bind_post_task.h" 14 15 namespace base { 16 17 // OVERVIEW: 18 // 19 // ConcurrentClosures is a OnceClosure version of ConcurrentCallbacks<T> and an 20 // alternative to BarrierClosure, it dispenses OnceClosures via CreateClosure() 21 // and invokes the closure passed to Done() after all prior closures have been 22 // run. 23 // 24 // ConcurrentClosures is intended to be used over BarrierClosure in 25 // cases where the count is unknown prior to requiring a closure to start a 26 // task, and for cases where the count is manually derived from the code and 27 // subject to human error. 28 // 29 // IMPORTANT NOTES: 30 // 31 // - ConcurrentClosures is NOT thread safe. 32 // - The done closure will NOT be run synchronously, it will be PostTask() to 33 // the sequence that Done() was invoked on. 34 // - ConcurrentClosures cannot be used after Done() is called, a CHECK verifies 35 // this. 36 // 37 // TYPICAL USAGE: 38 // 39 // void DoABC(OnceClosure closure) { 40 // base::ConcurrentClosures concurrent; 41 // 42 // DoA(concurrent.CreateClosure()); 43 // DoB(concurrent.CreateClosure()); 44 // DoC(concurrent.CreateClosure()); 45 // 46 // std::move(concurrent).Done(closure); 47 // } 48 49 class BASE_EXPORT ConcurrentClosures { 50 public: 51 ConcurrentClosures(); 52 ~ConcurrentClosures(); 53 54 // Create a closure for the done closure to wait for. 55 [[nodiscard]] OnceClosure CreateClosure(); 56 57 // Finish creating concurrent closures and provide done closure to run once 58 // all prior closures have executed. 59 // `this` is no longer usable after calling Done(), must be called with 60 // std::move(). 61 void Done(OnceClosure done_closure, const Location& location = FROM_HERE) &&; 62 63 private: 64 class Info { 65 public: 66 Info(); 67 ~Info(); 68 69 void Run(); 70 71 size_t pending_ GUARDED_BY_CONTEXT(sequence_checker_) = 0u; 72 OnceClosure done_closure_ GUARDED_BY_CONTEXT(sequence_checker_); 73 SEQUENCE_CHECKER(sequence_checker_); 74 }; 75 76 RepeatingClosure info_run_closure_; 77 // info_ is owned by info_run_closure_. 78 raw_ptr<Info> info_; 79 }; 80 81 } // namespace base 82 83 #endif // BASE_FUNCTIONAL_CONCURRENT_CLOSURES_H_ 84