How to keep threads untangled when changing vector? c++ - c++

This program will crash cause the threads are tangled... One could be pushing while the other is trying to erase.
How can I make this work?
#include <thread>
#include <vector>
using namespace std;
vector<int> v_test;
void push()
{
v_test.push_back(0);
}
void erase()
{
if (v_test.size() > 0)
{
v_test.erase(v_test.begin());
}
}
int main()
{
thread w0(push);
thread w1(erase);
while (true) { Sleep(1000); }
return 0;
}

You need to synchronize the threads so they coordinate their access to the vector. For example, by using a std::mutex, eg:
#include <thread>
#include <mutex>
#include <vector>
using namespace std;
vector<int> v_test;
mutex m_sync;
void push()
{
lock_guard<mutex> lock(m_sync);
v_test.push_back(0);
}
void erase()
{
lock_guard<mutex> lock(m_sync);
if (v_test.size() > 0)
{
v_test.erase(v_test.begin());
}
}
int main()
{
thread w0(push);
thread w1(erase);
while(true) {Sleep(1000);}
return 0;
}

Related

Problem with function push_back() and push_front() with class list in c++

I'm trying to do this simple program, where I want to use the take and append functions, which access a buffer implemented with a list, in a producer-consumer problem:
#ifndef buf_h
#define buf_h
#include <list>
using std::list;
#include <mutex>
using std::mutex;
#include <condition_variable>
using std::condition_variable;
class Buffer
{
public:
Buffer(int cap);
void append(int shift);
int take();
private:
list<double> Buffer_;
int capacity_;
int count_;
mutex mutex_;
condition_variable not_full_;
condition_variable not_empty_;
};
#endif
This is buffer:
#include "buf.h"
#include <list>
using std::list;
#include <mutex>
using std::mutex;
using std::unique_lock;
#include <condition_variable>
using std::condition_variable;
Buffer::Buffer(int capacity)
: Buffer_(capacity,0), capacity_{capacity}, count_{0}
{
}
void Buffer::append(int shift)
{
unique_lock<mutex> mlock(mutex_);
while(count_== capacity_)
not_full_.wait(mlock);
Buffer_.push_back(shift);
++count_;
not_empty_.notify_one();
}
int Buffer::take()
{
unique_lock<mutex> mlock(mutex_);
while(count_ == 0)
not_empty_.wait(mlock);
int w = Buffer_.front();
Buffer_.pop_front();
--count_;
not_full_.notify_one();
return w;
}
This is main:
#include <iostream>
using std::cout;
using std::endl;
#include <fstream>
using std::ifstream;
#include <thread>
using std::thread;
#include "buf.h"
Buffer B1{20};
void producer(int id){
B1.append(id);
}
void consumer(){
int w = B1.take();
cout<< w <<endl;
}
int main()
{
for(int i=0; i<5; ++i){
thread prod(producer, i);
thread cons(consumer);
prod.join();
cons.join();
}
return 0;
}
I don't understand why if I use push_back() in append, I get all 0 as output, when instead I should get this:
0
1
2
3
4
If I use push_front() the output is correct. Can anyone help me?
In your constructor:
Buffer_(capacity,0)
This does not do what you think it does. If you inspect what's in the Buffer_ immediately after construction you will discover that it's not empty, and the resulting program's behavior becomes easy to explain.
TLDR: the initializes the buffer with a whole bunch of values, which are all 0, which completely messes up the logic in the rest of the code which assumes that the buffer is initially empty.

SIGABRT in critical section simulation C++ code

I am new to threads, I am trying to simulate the critical section race condition problem in this code.
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
using namespace std::chrono;
int x = 20;
void increment()
{
++x;
}
void decrement()
{
--x;
}
int main()
{
thread t1(increment);
thread t2(decrement);
cout << x;
return 0;
}
But, this code terminates with SIGABRT.
terminate called without an active exception
21
Why I am getting SIGABRT in this code?
You must call join for the threads so that they are properly terminated
t1.join();
t2.join();

Using a boost::asio::deadline_timer per thread not working

I'm newbie here, so if I have any errors just tell me.
The problem is that I have two processes and I want them to execute concurrently because they take too much time. So I thought to implement a class timer which manage its own boost::asio::io_service and create a thread for this io_service. The code is the following:
timer.hpp
#include <iostream>
#include <string>
#include <functional>
#include <thread>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
class timer
{
public:
timer(std::function<void(void)> task,
int time)
: io__(),
timer__(io__, boost::posix_time::milliseconds(time)),
repetitive_task__(task),
time_wait__(time)
{
timer__.async_wait(boost::bind(&timer::loop, this));
}
void start()
{
thread__ = std::thread([this](){
io__.run();
});
thread__.join();
}
void loop()
{
repetitive_task__();
timer__.expires_at(timer__.expires_at() + boost::posix_time::milliseconds(time_wait__));
timer__.async_wait(boost::bind(&timer::loop, this));
}
void stop()
{
timer__.cancel();
io__.stop();
}
private:
boost::asio::io_service io__;
boost::asio::deadline_timer timer__;
std::function<void(void)> repetitive_task__;
int time_wait__;
std::thread thread__;
};
For testing it, I have the simplest main I could think:
main.cpp
#include "timer.hpp"
void test1()
{
printf("action1 \n");
}
void test2()
{
printf("action 2 \n");
}
int main(int argc, char* argv[])
{
timer timer1(&test1, 100);
timer timer2(&test2, 50);
timer1.start();
timer2.start();
return 0;
}
And the result is always action1. Never action2.
I've been looking for how to implement timers properly like in this post or in this example of boost, but I still don't understand what I am doing wrong.
Thanks in advance

event dispatcher using std::unique_ptr and std::deque in c++11

I have just written the source code below to dispatch events properly by using std::unique_ptr and std::deque, but I am not sure how accurate it is. I know it is not a good question but could someone evaluate it, is there any weird issue? In addition, I don't have any performance concern.
Thanks in advance.
- Volkan
#include <iostream>
#include <deque>
#include <mutex>
#include <memory>
#include <chrono>
#include <thread>
using namespace std;
class Event {
public:
Event(int a) : m_a(a)
{ }
void print()
{
cout << m_a << endl;
}
private:
int m_a;
};
class EventQueue {
public:
unique_ptr<Event> pop()
{
lock_guard<mutex> lock(m_Mutex);
unique_ptr<Event> p = nullptr;
if (!m_Queue.empty()) {
p = move(m_Queue.back());
m_Queue.pop_back();
}
return p;
}
void push(unique_ptr<Event> p)
{
lock_guard<mutex> lock(m_Mutex);
m_Queue.push_front(move(p));
}
private:
deque<unique_ptr<Event>> m_Queue;
mutex m_Mutex;
};
EventQueue evq;
void EventHandler()
{
while (true) {
unique_ptr<Event> p = evq.pop();
if (p)
p->print();
else
this_thread::sleep_for(chrono::seconds(10));
}
}
int main()
{
std::thread first (EventHandler);
while (true) {
int a;
cin >> a;
unique_ptr<Event> ev(new Event(a));
evq.push(move(ev));
}
first.join();
return 0;
}

Waiting for async operations

I want to implement a mechanism that allows me to block program flow until an async operation has completed. (Mostly to be used in unit tests where there is no message loop.)
The code I have creates a thread and waits for a condition notification inside the thread:
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <thread>
struct Blocker {
Blocker() :
wait_thread([this]() {
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
cond.wait(lck);
})
{
}
void wait() { wait_thread.join(); }
void notify() { cond.notify_one(); }
std::condition_variable cond;
std::thread wait_thread;
};
template<typename Callback>
void async_operation(const Callback & cb) { cb(); }
int main() {
Blocker b;
async_operation([&](){ b.notify(); });
b.wait();
}
The problem is that it often deadlocks because the call to notify occurs before the thread even started. How should I fix this?
#include <mutex>
#include <condition_variable>
struct blocker
{
blocker () : done (false) {}
void
notify ()
{
std::unique_lock<std::mutex> lock (m);
done = true;
c.notify_all ();
}
void
wait ()
{
std::unique_lock<std::mutex> lock (m);
while (!done)
c.wait (lock);
}
bool done;
std::mutex m;
std::condition_variable c;
};