C++: implementation of simple latch arrive_and_wait using std::condition_variable - c++

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!

Related

How can I pass a std::atomic<int> variable to a function within a thread

I'm having trouble with a very basic program.
I want to do a monitoring function that can access two int who are constantly incremented in two other threads.
Here is my code and I compile with either gcc -std=c++14 Monitoring.cpp -pthread or gcc -std=c++11 Monitoring.cpp -pthread:
#include <thread>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <chrono>
#include <atomic>
void monitor_function(std::atomic<int>& a1,std::atomic<int>& a2)
{
while(1){
std::this_thread::sleep_for (std::chrono::milliseconds(1000));
std::cout<<"a1 = "<<a1<<std::endl;
std::cout<<"a2 = "<<a2<<std::endl;
}
}
void thread_function_one(std::atomic<int>& a1)
{
while (1){
a1++;
}
}
void thread_function_two(std::atomic<int>& a2)
{
while (1){
a2++;
}
}
int main()
{
std::atomic<int> a1(0);
std::atomic<int> a2(0);
std::thread t1(thread_function_one,a1);
std::thread t2(thread_function_two,a2);
std::thread t3(monitor_function,a1,a2);
return 0;
}
Can you give me direction on how to use atomic variable inside threads ?
Thanks
EDIT :
I added protection and joined the threads :
#include <thread>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <chrono>
#include <atomic>
void monitor_function(std::atomic<int>& a1,std::atomic<int>& a2)
{
while(1){
std::this_thread::sleep_for (std::chrono::milliseconds(1000));
std::cout<<"a1 = "<<a1<<std::endl;
std::cout<<"a2 = "<<a2<<std::endl;
}
}
void thread_function_one(std::atomic<int>& a1)
{
while (1){
a1++;
if (a1 > 1000000){
a1 = -1000000;
}
}
}
void thread_function_two(std::atomic<int>& a2)
{
while (1){
a2++;
if (a2 > 1000000){
a2 = -1000000;
}
}
}
int main()
{
std::atomic<int> a1(0);
std::atomic<int> a2(0);
auto t1 = std::thread(thread_function_one,a1);
auto t2 = std::thread(thread_function_two,a2);
auto t3 = std::thread(monitor_function,a1,a2);
t1.join();
t2.join();
t3.join();
return 0;
}
Still got lot of compilation error, can launch my program
EDIT 2 : added std::ref around a1 and a2 and it works, thanks.
auto t1 = std::thread(thread_function_one,std::ref(a1));
auto t2 = std::thread(thread_function_two,std::ref(a2));
auto t3 = std::thread(monitor_function,std::ref(a1),std::ref(a2));

multithreading consumer not producing same output as input using boost ringbuffer

In my main program I am copying a string buffer into a boost ring buffer and then trying to consume that data in a created thread and writing to a file. In the main thread also I am writing the same data to a file but both input and output file is not matching.
I feel I am doing something incredibly stupid. Please help. Also, if there are any suggesting to improve the code that would really be appreciated.
#include <iostream>
#include <vector>
#include <boost/circular_buffer.hpp>
#include <numeric>
#include <assert.h>
#include <thread>
#include <mutex>
#include <chrono>
#include <time.h>
#include <cstdint>
#include <fstream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::fstream;
using std::string;
#define SOME_FIXED_HARDCODED_NUMBER 40980
class MyClass {
public:
std::vector<int8_t> vec;
public:
MyClass(std::vector<int8_t> v){ vec = v; }
};
boost::circular_buffer<MyClass> cb(300);
int waiting = 1;
std::mutex my_mutex;
FILE *out_file;
FILE *in_file;
void foo()
{
while (waiting) {
std::unique_lock<std::mutex> lock(my_mutex);
if (!cb.size() || waiting == 0) {
lock.unlock();
continue;
}
if (!waiting)
break;
MyClass local_buf = cb.front();
cb.pop_front();
fwrite(local_buf.vec.data(), 1, local_buf.vec.size(), out_file);
}
}
int main(int argc, char* argv[])
{
out_file = fopen("output_data.raw", "w");
in_file = fopen("input_data.raw", "w");
std::thread th1(foo);
char *buf = {"abc"};
int counter = 0;
std::vector<int8_t> mem;
mem.insert(mem.end(), buf, buf + strlen(buf));
while (counter < SOME_FIXED_HARDCODED_NUMBER)
{
{
std::unique_lock<std::mutex> lock(my_mutex);
/* if the circular buffer is full then wait for consumer to pull the data */
while (cb.full()) {
lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::unique_lock<std::mutex> lock(my_mutex);
}
cb.push_front(MyClass(mem));
fwrite(mem.data(), 1, mem.size(), in_file);
}
counter++;
}
waiting = 0;
th1.join();
fclose(out_file);
fclose(in_file);
return 0;
}
while (cb.full()) {
lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
>>> std::unique_lock<std::mutex> lock(my_mutex);
}
The marked unique_lock doesn't do anything as it will go out of scope immediately and unlock the mutex. Hence once you leave the loop the mutex is not locked and you have a racecondition. Instead, you should use lock.lock() to relock the mutex.
There is a few more bugs. You are not waiting for your foo thread to actually drain the buffer. It will stop as soon as the waiting flag is set by the main thread. Also, waiting should be an atomic.

thread pooling in c++ - how to end the program

I've implemented thread pooling following the answer of Kerrek SB in this question.
I've implemented MPMC queue for the functions and vector threads for the threads.
Everything worked perfectly, except that I don't know how to terminate the program, in the end if I just do thread.join since the thread is still waiting for more tasks to do, it will not join and the main thread will not continue.
Any idea how to end the program correctly?
For completeness, this is my code:
function_pool.h
#pragma once
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
class Function_pool
{
private:
std::queue<std::function<void()>> m_function_queue;
std::mutex m_lock;
std::condition_variable m_data_condition;
public:
Function_pool();
~Function_pool();
void push(std::function<void()> func);
std::function<void()> pop();
};
function_pool.cpp
#include "function_pool.h"
Function_pool::Function_pool() : m_function_queue(), m_lock(), m_data_condition()
{
}
Function_pool::~Function_pool()
{
}
void Function_pool::push(std::function<void()> func)
{
std::unique_lock<std::mutex> lock(m_lock);
m_function_queue.push(func);
// when we send the notification immediately, the consumer will try to
get the lock , so unlock asap
lock.unlock();
m_data_condition.notify_one();
}
std::function<void()> Function_pool::pop()
{
std::unique_lock<std::mutex> lock(m_lock);
m_data_condition.wait(lock, [this]() {return !m_function_queue.empty();
});
auto func = m_function_queue.front();
m_function_queue.pop();
return func;
// Lock will be released
}
main.cpp
#include "function_pool.h"
#include <string>
#include <iostream>
#include <mutex>
#include <functional>
#include <thread>
#include <vector>
Function_pool func_pool;
void example_function()
{
std::cout << "bla" << std::endl;
}
void infinite_loop_func()
{
while (true)
{
std::function<void()> func = func_pool.pop();
func();
}
}
int main()
{
std::cout << "stating operation" << std::endl;
int num_threads = std::thread::hardware_concurrency();
std::cout << "number of threads = " << num_threads << std::endl;
std::vector<std::thread> thread_pool;
for (int i = 0; i < num_threads; i++)
{
thread_pool.push_back(std::thread(infinite_loop_func));
}
//here we should send our functions
func_pool.push(example_function);
for (int i = 0; i < thread_pool.size(); i++)
{
thread_pool.at(i).join();
}
int i;
std::cin >> i;
}
Your problem is located in infinite_loop_func, which is an infinite loop and by result doesn't terminate. I've read the previous answer which suggests throwing an exception, however, I don't like it since exceptions should not be used for the regular control flow.
The best way to solve this is to explicitly deal with the stop condition. For example:
std::atomic<bool> acceptsFunctions;
Adding this to the function pool allows you to clearly have state and to assert that no new functions being added when you destruct.
std::optional<std::function<void()>> Function_pool::pop()
Returning an empty optional (or function in C++14 and before), allows you to deal with an empty queue. You have to, as condition_variable can do spurious wakeups.
With this, m_data_condition.notify_all() can be used to wake all threads.
Finally we have to fix the infinite loop as it doesn't cover overcommitment and at the same time allows you to execute all functions still in the queue:
while (func_pool.acceptsFunctions || func_pool.containsFunctions())
{
auto f = func_pool.pop();
If (!f)
{
func_pool.m_data_condition.wait_for(1s);
continue;
}
auto &function = *f;
function ();
}
I'll leave it up to you to implement containsFunctions() and clean up the code (infinite_loop_func as member function?) Note that with a counter, you could even deal with background task being spawned.
You can always use a specific exception type to signal to infinite_loop_func that it should return...
class quit_worker_exception: public std::exception {};
Then change infinite_loop_func to...
void infinite_loop_func ()
{
while (true) {
std::function<void()> func = func_pool.pop();
try {
func();
}
catch (quit_worker_exception &ex) {
return;
}
}
}
With the above changes you could then use (in main)...
/*
* Enqueue `thread_pool.size()' function objects whose sole job is
* to throw an instance of `quit_worker_exception' when invoked.
*/
for (int i = 0; i < thread_pool.size(); i++)
func_pool.push([](){ throw quit_worker_exception(); });
/*
* Now just wait for each worker to terminate having received its
* quit_worker_exception.
*/
for (int i = 0; i < thread_pool.size(); i++)
thread_pool.at(i).join();
Each instance of infinite_loop_func will dequeue one function object which, when called, throws a quit_worker_exception causing it to return.
Follwoing [JVApen](https://stackoverflow.com/posts/51382714/revisions) suggestion, I copy my code in case anyone will want a working code:
function_pool.h
#pragma once
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <cassert>
class Function_pool
{
private:
std::queue<std::function<void()>> m_function_queue;
std::mutex m_lock;
std::condition_variable m_data_condition;
std::atomic<bool> m_accept_functions;
public:
Function_pool();
~Function_pool();
void push(std::function<void()> func);
void done();
void infinite_loop_func();
};
function_pool.cpp
#include "function_pool.h"
Function_pool::Function_pool() : m_function_queue(), m_lock(), m_data_condition(), m_accept_functions(true)
{
}
Function_pool::~Function_pool()
{
}
void Function_pool::push(std::function<void()> func)
{
std::unique_lock<std::mutex> lock(m_lock);
m_function_queue.push(func);
// when we send the notification immediately, the consumer will try to get the lock , so unlock asap
lock.unlock();
m_data_condition.notify_one();
}
void Function_pool::done()
{
std::unique_lock<std::mutex> lock(m_lock);
m_accept_functions = false;
lock.unlock();
// when we send the notification immediately, the consumer will try to get the lock , so unlock asap
m_data_condition.notify_all();
//notify all waiting threads.
}
void Function_pool::infinite_loop_func()
{
std::function<void()> func;
while (true)
{
{
std::unique_lock<std::mutex> lock(m_lock);
m_data_condition.wait(lock, [this]() {return !m_function_queue.empty() || !m_accept_functions; });
if (!m_accept_functions && m_function_queue.empty())
{
//lock will be release automatically.
//finish the thread loop and let it join in the main thread.
return;
}
func = m_function_queue.front();
m_function_queue.pop();
//release the lock
}
func();
}
}
main.cpp
#include "function_pool.h"
#include <string>
#include <iostream>
#include <mutex>
#include <functional>
#include <thread>
#include <vector>
Function_pool func_pool;
class quit_worker_exception : public std::exception {};
void example_function()
{
std::cout << "bla" << std::endl;
}
int main()
{
std::cout << "stating operation" << std::endl;
int num_threads = std::thread::hardware_concurrency();
std::cout << "number of threads = " << num_threads << std::endl;
std::vector<std::thread> thread_pool;
for (int i = 0; i < num_threads; i++)
{
thread_pool.push_back(std::thread(&Function_pool::infinite_loop_func, &func_pool));
}
//here we should send our functions
for (int i = 0; i < 50; i++)
{
func_pool.push(example_function);
}
func_pool.done();
for (unsigned int i = 0; i < thread_pool.size(); i++)
{
thread_pool.at(i).join();
}
}

c++ Run every 10 minute

I want this program run every start(call) 10min.
But I did not find a solution how-to call(start) Program every 10 minutes, on c++ code (man.exe).
I would like to use the code in visual studio 2013
int runevery() {
system("start man.exe");
return true;
}
Call:
#ifdef MAN_RUN
runevery();
#endif
Thank you for your help in advance!
You can create another thread that executes that function periodically until stopped. Example:
#include <mutex>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
#include <condition_variable>
class PeriodicAction {
std::mutex m_;
std::condition_variable c_;
bool stop_ = false;
std::function<void()> const f_;
std::chrono::seconds const initial_delay_;
std::chrono::seconds const delay_;
std::thread thread_;
bool wait(std::chrono::seconds delay) {
std::unique_lock<std::mutex> lock(m_);
c_.wait_for(lock, delay, [this]() { return stop_; });
return !stop_;
}
void thread_fn() {
for(auto delay = initial_delay_; this->wait(delay); delay = delay_)
f_();
}
public:
PeriodicAction(std::chrono::seconds initial_delay,
std::chrono::seconds delay,
std::function<void()> f)
: f_(move(f))
, initial_delay_(initial_delay)
, delay_(delay)
, thread_(&PeriodicAction::thread_fn, this)
{}
~PeriodicAction() {
this->stop();
thread_.join();
}
void stop() {
{
std::unique_lock<std::mutex> lock(m_);
stop_ = true;
}
c_.notify_one();
}
};
char const* now_c_str() {
auto time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
return std::ctime(&time_t);
}
int main(int ac, char**) {
using namespace std::literals::chrono_literals;
// Print current time for the next 5 seconds and then terminate.
PeriodicAction a(0s, 1s, []() { std::cout << now_c_str(); });
std::this_thread::sleep_for(5s);
}
Applying to your case:
PeriodicAction a(0s, 600s, [](){ system("start man.exe"); });
I don't think this is a good idea, but it's easy to achieve like this:
#include <thread>
#include <chrono>
int main()
{
while (true)
{
std::this_thread::sleep_for(std::chrono::minutes(10));
system("man.exe");
}
}
I still think as per my earlier comment that a scheduled task on Windows would be better behaved and easier configurable.

Boost deadline_timer is not generating event when i am using expire_at?

class header file
//dividandconquer.h
#ifndef DIVIDANDCONQUER_H
#define DIVIDANDCONQUER_H
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/date.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
using namespace boost::posix_time;
using namespace boost::gregorian;
class dividandconquer
{
public:
dividandconquer(boost::asio::io_service& io);
int lb =0;
int ub =1000;
int mb =0;
ptime t1;
ptime finaltimer;
void reset(int);
void print();
private:
boost::asio::deadline_timer timer_;
int count_;
};
#endif // DIVIDANDCONQUER_H
inside constructor i am trying to trigger timer at specific time(using expire_at) but its not working. But if i am using expires_from_now it works fine.
File name :dividandconquer.cpp
#include "dividandconquer.h"
dividandconquer::dividandconquer(boost::asio::io_service& io)
: timer_(io),
count_(0)
{
t1=ptime( (boost::gregorian::day_clock::local_day()), hours(15)+minutes(12));
timer_.expires_at(t1);
timer_.async_wait(boost::bind(&dividandconquer::print, this));
}
void dividandconquer::reset(int upordown)// 0 means lowebound 1 means uperbound
{
if (mb>0)
{
if (0==upordown)
{ mb=(lb+ub)/2;
ub=mb;
}
else
{
mb=(ub-lb)/2;
lb=mb;
}
}
}
void dividandconquer::print()
{
if (count_ < 5)
{
std::cout << count_ << "\n";
++count_;
//timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
// timer_.async_wait(boost::bind(&printer::print, this));
}
}
main file
#include <QApplication>
#include "dividandconquer.h"
#include <boost/asio.hpp>
int main(int argc, char *argv[])
{
boost::asio::io_service io;
dividandconquer d1(io);
io.run();
return 0;
}
The main problem is that asio::deadline_timer expects absolute timepoints in UTC but gregorian::day_clock::local_day() returns the local date without any time component; I believe this is a working (and reduced) version of what you're looking for:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/system/error_code.hpp>
using namespace boost::posix_time;
using boost::system::error_code;
struct dividandconquer {
explicit dividandconquer(boost::asio::io_service& io) : timer_(io) {
timer_.expires_at(microsec_clock::universal_time() + milliseconds(500));
timer_.async_wait([this](error_code const&){ print(); });
}
void print() {
if (count_ < 5) {
std::cout
<< microsec_clock::universal_time().time_of_day().ticks()
<< " :: " << count_++ << '\n';
timer_.expires_at(timer_.expires_at() + milliseconds(500));
timer_.async_wait([this](error_code const&){ print(); });
}
}
private:
boost::asio::deadline_timer timer_;
int count_{};
};
int main() {
boost::asio::io_service io;
dividandconquer d1{io};
io.run();
}
Online Demo
(Or see here if you really want to stick with bind over using a lambda.)
Since you're using C++11, it's best to avoid involving Boost.Date_Time in any way and just use the standard library instead:
#include <chrono>
#include <boost/asio/steady_timer.hpp>
using namespace std::chrono;
struct dividandconquer {
explicit dividandconquer(boost::asio::io_service& io) : timer_(io) {
timer_.expires_at(steady_clock::now() + milliseconds(500));
timer_.async_wait([this](error_code const&){ print(); });
}
void print() {
if (count_ < 5) {
std::cout
<< steady_clock::now().time_since_epoch().count()
<< " :: " << count_++ << '\n';
timer_.expires_at(timer_.expires_at() + milliseconds(500));
timer_.async_wait([this](error_code const&){ print(); });
}
}
private:
boost::asio::steady_timer timer_;
int count_{};
};
Online Demo