Lets say I have Object A and Object B. ObjA creates multiple 'ObjB's and keeps a pointer to each, then detaches a thread on each object B to do work. I want to implement a barrier in ObjA that only unlocks whenever all 'ObjB's have reached a certain internal condition within their work functions.
How can I create a barrier with a dynamic count within ObjA, and then make ObjB aware of that barrier so that it can arrive at the barrier? I wanted to use std::barrier but I've had problems trying to do so.
Thus far I cannot make a std::barrier member variable in ObjA because it requires an input size which I will only know once ObjA is constructed. If I create the barrier inside of the busy function of ObjA, then any signal function that ObjB calls to A with won't have scope to it.
Is the best approach to do some homespun semaphore with busy waiting?
You can use a conditional variable.
#include <iostream>
#include <condition_variable>
#include <thread>
#include <vector>
std::condition_variable cv;
std::mutex cv_m; // This mutex is used for three purposes:
// 1) to synchronize accesses to count
// 3) for the condition variable cv
int total_count = 10; // This is count of objBs
int count = total_count;
void obj_b_signals()
{
// Do something..
bool certainCondition = true;
// We have reached the condition..
if (certainCondition) {
{
std::lock_guard<std::mutex> lk(cv_m);
count--;
}
std::cerr << "Notifying...\n";
cv.notify_one();
}
}
int main()
{
// obj A logic
std::vector<std::thread> threads;
for (size_t i=0; i<total_count; ++i) {
threads.emplace_back(std::thread(obj_b_signals));
}
{
std::unique_lock<std::mutex> lk(cv_m);
std::cerr << "Waiting for ObjBs to reach a certain condition... \n";
cv.wait(lk, []{return count == 0;});
std::cerr << "...finished waiting. count == 0\n";
}
// Do something else
for (std::thread & t: threads) {
t.join();
}
}