I have a simple program with two threads, one that pushes a packaged_task into a deque, and other that executes it. In the tasks there is a this_thread::sleep_for, and I would expect that only the "process" thread would wait for it, but both are waiting, making the execution sequential. What I'm missing?
#include <future>
#include <iostream>
#include <deque>
std::mutex m;
std::condition_variable cv;
std::deque<std::packaged_task<void(int)>> deque;
void post() {
int id = 0;
auto lambda = [](int id) {
std::this_thread::sleep_for(std::chrono::seconds(std::rand() % 10 + 1));
std::cout << id << std::endl;
};
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::packaged_task<void(int)> task(lambda);
task(id++);
std::lock_guard<std::mutex> lg(m);
deque.emplace_back(std::move(task));
cv.notify_one();
}
}
void process() {
std::deque<std::packaged_task<void(int)>> to_exec;
while (true) {
while (!to_exec.empty()){
std::future<void> fut = to_exec.front().get_future();
fut.get();
to_exec.pop_front();
}
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []() {return !deque.empty(); });
while (!deque.empty()) {
to_exec.push_back(std::move(deque.front()));
deque.pop_front();
}
}
}
int main() {
std::thread tpost(post);
std::thread tprocess(process);
tpost.join();
tprocess.join();
}
I think more effective will be use std::async instead a sleeping random seconds...
Related
There is a simple example of using Condition_variable:
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
std::mutex mtx;
std::condition_variable cv;
int global_status = 0;
void print_id(int id)
{
std::unique_lock<std::mutex> lck(mtx);
while (global_status == 0)
{
cv.wait(lck);
}
std::cout << "thread " << id << '\n';
}
int main()
{
std::thread threads[10];
for (int i = 0; i < 10; ++i)
{
threads[i] = std::thread(print_id, i);
}
std::cout << "Start" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
{
std::unique_lock<std::mutex> lck(mtx);
global_status = 1;
cv.notify_all();
}
for (auto& th : threads) th.join();
return 0;
}
I still can't figure out why block the global_status variable when I change its value?
I change the value global_status from only one thread - why then they block it mutex ? Or is it not necessary?
I change the value global_status from only one thread - why then they block it mutex
You need the mutex because you read the value in different threads.
I have a simple program below where some long running process someFn works, sets a state, works sets a state, works and sets a state.
While someFn is running, I want the main thread to query the state it's setting for the lifetime of someFn.
Obviously this code is incorrect because T is joinable until it actually joins and this program does not halt.
How do I correctly get the main thread to loop for the lifetime of T and stop looping as soon as T has terminated?
#include <iostream>
#include <thread>
#include <chrono>
int STATE = 0;
static std::mutex mtx;
void setState(int newState) {
std::lock_guard<std::mutex> lg(mtx);
STATE = newState;
}
int getState() {
std::lock_guard<std::mutex> lg(mtx);
return STATE;
}
void someFn() {
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(0);
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(1);
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(2);
}
int main()
{
std::thread T(someFn);
while (T.joinable()) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << getState() << std::endl;
}
T.join();
return 0;
}
Thanks!
Just with std::thread you can't.
But you can easily craft your own signal. For example:
#include <atomic>
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>
int STATE = 0;
static std::mutex mtx;
void setState(int newState) {
std::lock_guard<std::mutex> lg(mtx);
STATE = newState;
}
int getState() {
std::lock_guard<std::mutex> lg(mtx);
return STATE;
}
void someFn(std::atomic<bool>& isDone) {
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(0);
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(1);
std::this_thread::sleep_for(std::chrono::seconds(1));
setState(2);
isDone.store(true);
}
int main() {
std::atomic<bool> isDone{false};
std::thread T(someFn, std::ref(isDone));
while(!isDone.load()) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << getState() << std::endl;
}
T.join();
return 0;
}
You don't need a mutex or other synchronization for std::atomic because it is already thread safe.
I want to keep my code clean and do the things right, to any std::thread I need to do join or detach, but how can I wait (at the main thread) for another thread without blocking the execution of the main thread?
void do_computation()
{
// Calculate 1000 digits of Pi.
}
int main()
{
std::thread td1(&do_computation);
while (running)
{
// Check if thread td1 finish and if yes print a message
// Here are some stuff of the main to do...
// Print to UI, update timer etc..
}
// If the thread has not finished yet here, just kill it.
}
The answer is semaphores. You can use a binary semaphore to synchronize your threads.
You may use System V semaphores or pthread mutexes, but they are somehow legacy in C++. Using Tsuneo Yoshioka's answer, we could implement a C++ way of semaphore, though.
#include <mutex>
#include <condition_variable>
class Semaphore {
public:
Semaphore (int count_ = 0)
: count(count_) {}
inline void notify()
{
std::unique_lock<std::mutex> lock(mtx);
count++;
cv.notify_one();
}
inline void wait()
{
std::unique_lock<std::mutex> lock(mtx);
while(count == 0){
cv.wait(lock);
}
count--;
}
private:
std::mutex mtx;
std::condition_variable cv;
int count;
};
Your implementation may make use of the Semaphore class, like so.
void do_computation()
{
//calculate 1000 digits of Pi.
semaphore.notify();
}
int main()
{
Semaphore semaphore(0);
std::thread td1(&do_computation);
semaphore.wait();
}
You can use std::promise and std::future. More info here and here.
#include <vector>
#include <thread>
#include <future>
#include <numeric>
#include <iostream>
#include <chrono>
void accumulate(std::vector<int>::iterator first,
std::vector<int>::iterator last,
std::promise<int> accumulate_promise)
{
int sum = std::accumulate(first, last, 0);
accumulate_promise.set_value(sum); // Notify future
}
void do_work(std::promise<void> barrier)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
barrier.set_value();
}
int main()
{
// Demonstrate using promise<int> to transmit a result between threads.
std::vector<int> numbers = { 1, 2, 3, 4, 5, 6 };
std::promise<int> accumulate_promise;
std::future<int> accumulate_future = accumulate_promise.get_future();
std::thread work_thread(accumulate, numbers.begin(), numbers.end(),
std::move(accumulate_promise));
accumulate_future.wait(); // wait for result
std::cout << "result=" << accumulate_future.get() << '\n';
work_thread.join(); // wait for thread completion
// Demonstrate using promise<void> to signal state between threads.
std::promise<void> barrier;
std::future<void> barrier_future = barrier.get_future();
std::thread new_work_thread(do_work, std::move(barrier));
barrier_future.wait();
new_work_thread.join();
}
pthreads has undefined behavior if multiple threads try to join the same thread:
If multiple threads simultaneously try to join with the same thread,
the results are undefined.
Is the same true for boost::threads? The documentation does not appears to specify this.
If it is undefined, then what would be a clean way for multiple threads to wait on one thread completing?
If it is undefined, then what would be a clean way for multiple threads to wait on one thread completing?
The clean way would be for that one thread to inform the others that it is complete. A packaged_task contains a future which can be waited on, which can help us here.
Here's one way of doing that. I have used std::thread and std::packaged_task, but you could use the boost equivalents just as well.
#include <thread>
#include <mutex>
#include <future>
#include <vector>
#include <iostream>
void emit(const char* msg) {
static std::mutex m;
std::lock_guard<std::mutex> l(m);
std::cout << msg << std::endl;
std::cout.flush();
}
int main()
{
using namespace std;
auto one_task = std::packaged_task<void()>([]{
emit("waiting...");
std::this_thread::sleep_for(std::chrono::microseconds(500));
emit("wait over!");
});
// note: convert future to a shared_future so we can pass it
// to two subordinate threads simultaneously
auto one_done = std::shared_future<void>(one_task.get_future());
auto one = std::thread(std::move(one_task));
std::vector<std::thread> many;
many.emplace_back([one_done] {
one_done.wait();
// do my thing here
emit("starting thread 1");
});
many.emplace_back([one_done] {
one_done.wait();
// do my thing here
emit("starting thread 2");
});
one.join();
for (auto& t : many) {
t.join();
}
cout << "Hello, World" << endl;
return 0;
}
expected output:
waiting...
wait over!
starting thread 2
starting thread 1
Hello, World
I ended up using a boost::condition_variable... roughly:
class thread_wrapper {
boost::mutex mutex;
boost::condition_variable thread_done_condition;
bool thread_done = false;
void the_func() {
// ...
// end of the thread
{
boost:unique_lock<boost::mutex> lock(mutex);
thread_done = true;
}
thread_done_condition.notify_all();
}
void wait_until_done() {
boost::unique_lock<boost::mutex> lock(mutex);
thread_done_condition.wait(lock, [this]{ return thread_done; });
}
}
Then multiple callers can safely call wait_until_done().
It strikes me now that something like the following would also have worked:
class thread_wrapper {
public:
thread_wrapper() : thread([this]() { this->the_func(); }) { }
void wait_until_done() {
boost::unique_lock<boost::mutex> lock(join_mutex);
thread.join();
}
private:
void the_func() {
// ...
}
boost::mutex join_mutex;
boost::thread thread;
}
My program has three threads, and I am trying to learn about synchronization and thread safety. Below I outline what the different threads do, but I would like to learn how to use events instead to trigger each process in the different threads instead of infinitely reading (which is giving me concurrency issues).
Googling throws up many options but I'm not sure what is best to implement in this case - could you point the direction to a standard method/event that I could learn to best implement this?
I am doing this on VS 2012, and ideally I would not use external libraries e.g. boost.
Thread 1: receives a message and pushes it into a global queue, queue<my_class> msg_in.
Thread 2: on infinite loop (i.e. while(1) ); waits till if (!msg_in.empty()), does some processing, and pushes it into a global map<map<queue<my_class>>> msg_out.
while (1)
{
if (!msg_in.empty())
{
//processes
msg_map[i][j].push(); //i and j are int (irrelevant here)
}
}
Thread 3:
while (1)
{
if (msg_map.find(i) != msg_map.end())
{
if (!msg_map[i].find(j)->second.empty())
{
//processes
}
}
}
Your problems is a producer consumer problem. You can use condition variables for your events. There is one example of it here: http://en.cppreference.com/w/cpp/thread/condition_variable
I have adapted it to your example if your need it.
#include "MainThread.h"
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
bool ready = false;
bool processed = false;
void worker_thread(unsigned int threadNum)
{
// Wait until main() sends data
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return ready;});
}
std::cout << "Worker thread "<<threadNum <<" is processing data"<<std::endl;
// Send data back to main()
{
std::lock_guard<std::mutex> lk(m);
processed = true;
std::cout << "Worker thread "<< threadNum <<" signals data processing completed\n";
}
cv.notify_one();
}
int initializeData()
{
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "Data initialized"<<std::endl;
}
cv.notify_one();
return 0;
}
int consumerThread(unsigned int nbThreads)
{
std::atomic<unsigned int> nbConsumedthreads=0;
while (nbConsumedthreads<nbThreads)
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return processed;});
std::cout<<"Data processed counter="<<nbConsumedthreads << " "<< std::endl;
++nbConsumedthreads;
cv.notify_one();
}
return 0;
}
int main()
{
const unsigned int nbThreads=3;
std::thread worker1(worker_thread,1);
std::thread worker2(worker_thread,2);
std::thread worker3(worker_thread,3);
std::thread init(initializeData);
std::thread consume(consumerThread, nbThreads);
worker1.join();
worker2.join();
worker3.join();
init.join();
consume.join();
return 0;
}
Hope that helps, tell me if you need more info.