11// SPDX-License-Identifier: BSD-3-Clause
2- /* Copyright 2020, Intel Corporation */
2+ /* Copyright 2020-2021 , Intel Corporation */
33#ifndef THREAD_HELPERS_COMMON_HPP
44#define THREAD_HELPERS_COMMON_HPP
55
@@ -25,31 +25,58 @@ parallel_exec(size_t concurrency, Function f)
2525 }
2626}
2727
28+ class latch {
29+ public:
30+ latch (size_t desired) : counter(desired)
31+ {
32+ }
33+
34+ /* Returns true for the last thread arriving at the latch, false for all
35+ * other threads. */
36+ bool
37+ wait (std::unique_lock<std::mutex> &lock)
38+ {
39+ counter--;
40+ if (counter > 0 ) {
41+ cv.wait (lock, [&] { return counter == 0 ; });
42+ return false ;
43+ } else {
44+ /*
45+ * notify_call could be called outside of a lock
46+ * (it would perform better) but drd complains
47+ * in that case
48+ */
49+ cv.notify_all ();
50+ return true ;
51+ }
52+ }
53+
54+ private:
55+ std::condition_variable cv;
56+ size_t counter = 0 ;
57+ };
58+
2859/*
2960 * This function executes 'concurrency' threads and provides
30- * 'syncthreads' method (synchronization barrier) for f()
61+ * 'syncthreads' method (multi-use synchronization barrier) for f()
3162 */
3263template <typename Function>
3364void
3465parallel_xexec (size_t concurrency, Function f)
3566{
36- std::condition_variable cv;
3767 std::mutex m;
38- std::unique_ptr< size_t > counter =
39- std::unique_ptr< size_t >(new size_t ( 0 ));
68+ std::shared_ptr<latch> current_latch =
69+ std::shared_ptr<latch >(new latch (concurrency ));
4070
71+ /* Implements multi-use barrier (latch). Once all threads arrive at the
72+ * latch, a new latch is allocated and used by all subsequent calls to
73+ * syncthreads. */
4174 auto syncthreads = [&] {
4275 std::unique_lock<std::mutex> lock (m);
43- (*counter)++;
44- if (*counter < concurrency)
45- cv.wait (lock, [&] { return *counter >= concurrency; });
46- else
47- /*
48- * notify_call could be called outside of a lock
49- * (it would perform better) but drd complains
50- * in that case
51- */
52- cv.notify_all ();
76+ auto l = current_latch;
77+ if (l->wait (lock))
78+ current_latch =
79+ std::shared_ptr<latch>(new latch (concurrency));
5380 };
5481
5582 parallel_exec (concurrency, [&](size_t tid) { f (tid, syncthreads); });
0 commit comments