Could you please help me to implement a simple latch arrive_and_wait using std::condition_variable
? My project uses C++17 and so I can not use C++20 std::latch
. So, I am trying to implement a simple latch myself.
Here is the simplest example. The expected result is that "done 1"
, "done 2"
, and "done 3"
should be printed simultaneously.
/******************************************************************************/
#include <atomic>
#include <condition_variable>
#include <limits>
#include <chrono>
#include <cstddef>
#include <cstdlib>
#include <iostream>
#include <future>
#include <thread>
/******************************************************************************/
class Latch
{
public:
Latch(void) : expected(0) {}
void count_up(void)
{
if(expected < std::numeric_limits<Count>::max())
expected++;
else
{
std::cerr<<"#Error! Latch::count_up: expected: "<<expected<<std::endl;
exit(EXIT_FAILURE);
}
}
/**************************************/
void arrive_and_wait(void) // https://en.cppreference.com/w/cpp/thread/latch/arrive_and_wait
{
expected--;
while(expected>0); // busy-loop waiting; how to implement it using std::condition_variable ?
// cond.notify_all();
// std::mutex mutex;
// std::unique_lock lock(mutex);
// cond.wait(lock, [&expected=expected]{return expected.load()==0;});
}
/**************************************/
private:
using Count = uint_fast8_t;
std::atomic<Count> expected;
std::condition_variable cond;
};
/******************************************************************************/
void Run(const int delayInSeconds, Latch * const latch=nullptr)
{
if(latch) latch->count_up();
std::this_thread::sleep_for( std::chrono::seconds(delayInSeconds) );
if(latch) latch->arrive_and_wait();
}
/******************************************************************************/
int main(void)
{
std::cout<<"start...\n";
Latch latch;
auto f1 = std::async(Run, 2, &latch);
auto f2 = std::async(Run, 4, &latch);
auto f3 = std::async(Run, 8, &latch);
f1.get(); std::cout<<"done 1\n";
f2.get(); std::cout<<"done 2\n";
f3.get(); std::cout<<"done 3\n";
return EXIT_SUCCESS;
}
/******************************************************************************/
Thank you very much for your help!