Threading inside class with atomics and mutex c++ - c++

I wrote this sample program to mimic what I'm trying to do in a larger program.
I have some data that will come from the user and be passed into a thread for some processing. I am using mutexes around the data the flags to signal when there is data.
Using the lambda expression, is a pointer to *this send to the thread? I seem to be getting the behavior I expect in the cout statement.
Are the mutexes used properly around the data?
Is putting the atomics and mutexes as a private member of the class a good move?
foo.h
#pragma once
#include <atomic>
#include <thread>
#include <vector>
#include <mutex>
class Foo
{
public:
Foo();
~Foo();
void StartThread();
void StopThread();
void SendData();
private:
std::atomic<bool> dataFlag;
std::atomic<bool> runBar;
void bar();
std::thread t1;
std::vector<int> data;
std::mutex mx;
};
foo.c
#include "FooClass.h"
#include <thread>
#include <string>
#include <iostream>
Foo::Foo()
{
dataFlag = false;
}
Foo::~Foo()
{
StopThread();
}
void Foo::StartThread()
{
runBar = true;
t1 = std::thread([=] {bar(); });
return;
}
void Foo::StopThread()
{
runBar = false;
if(t1.joinable())
t1.join();
return;
}
void Foo::SendData()
{
mx.lock();
for (int i = 0; i < 5; ++i) {
data.push_back(i);
}
mx.unlock();
dataFlag = true;
}
void Foo::bar()
{
while (runBar)
{
if(dataFlag)
{
mx.lock();
for(auto it = data.begin(); it < data.end(); ++it)
{
std::cout << *it << '\n';
}
mx.unlock();
dataFlag = false;
}
}
}
main.cpp
#include "FooClass.h"
#include <iostream>
#include <string>
int main()
{
Foo foo1;
std::cout << "Type anything to end thread" << std::endl;
foo1.StartThread();
foo1.SendData();
// type something to end threads
char a;
std::cin >> a;
foo1.StopThread();
return 0;
}

You ensure that the thread is joined using RAII techniques? Check.
All data access/modification is either protected through atomics or mutexs? Check.
Mutex locking uses std::lock_guard? Nope. Using std::lock_guard wraps your lock() and unlock() calls with RAII. This ensures that even if an exception occurs while within the lock, that the lock is released.
Is putting the atomics and mutexes as a private member of the class a good move?
Its neither good nor bad, but in this scenario, where Foo is a wrapper for a std::thread that does work and controls the synchronization, it makes sense.
Using the lambda expression, is a pointer to *this send to the thread?
Yes, you can also do t1 = std::thread([this]{bar();}); to make it more explicit.
As it stands, with your dataFlag assignments after the locks, you may encounter problems. If you call SendData twice such that bar processes the first one but is halted before setting dataFlag = false so that the second call adds the data, sets the flag to true only to have bar set it back to false. Then, you'll have data that has been "sent" but bar doesn't think there's anything to process.
There may be other tricky situations, but this was just one example; moving it into the lock clears up that problem.
for example, your SendData should look like:
void Foo::SendData()
{
std::lock_guard<std::mutex> guard(mx);
for (int i = 0; i < 5; ++i) {
data.push_back(i);
}
dataFlag = true;
}

Related

How to make destructor wait until other thread's job complete?

I have one main thread that will send an async job to the task queue on the other thread. And this main thread can trigger a destroy action at any time, which could cause the program to crash in the async task, a piece of very much simplified code like this:
class Bomb {
public:
int trigger;
mutex my_mutex;
};
void f1(Bomb *b) {
lock_guard<std::mutex> lock(b->my_mutex); //won't work! Maybe b have been destructed!
sleep(1);
cout<<"wake up.."<<b->trigger<<"..."<<endl;
}
int main()
{
Bomb *b = new Bomb();
b->trigger = 1;
thread t1(f1, b);
sleep(1);
//lock here won't work
delete b;//in actual case it is triggered by outside users
t1.join();
return 0;
}
The lock in f1 won't work since the destructor can be called first and trying to read mutex will crash. Put lock in destructor or before the delete also won't work for the same reason.
So is there any better way in this situation? Do I have to put mutex in the global scope and inside destructor to solve the issue?
In code, my comment looks like this :
#include <future>
#include <mutex>
#include <iostream>
#include <chrono>
#include <thread>
// do not use : using namespace std;
class Bomb
{
public:
void f1()
{
m_future = std::async(std::launch::async,[this]
{
async_f1();
});
}
private:
void async_f1()
{
using namespace std::chrono_literals;
std::lock_guard<std::mutex> lock{ m_mtx };
std::cout << "wake up..\n";
std::this_thread::sleep_for(1s);
std::cout << "thread done.\n";
}
std::future<void> m_future;
std::mutex m_mtx;
};
int main()
{
{
std::cout << "Creating bomb\n";
Bomb b; // no need to use unecessary new
b.f1();
}
std::cout << "Bomb destructed\n";
return 0;
}

How to Share Mutex, Condition Variable and Queue between two Classes C++?

When trying to learn threads most examples suggests that I should put std::mutex, std::condition_variable and std::queue global when sharing data between two different threads and it works perfectly fine for simple scenario. However, in real case scenario and bigger applications this may soon get complicated as I may soon lose track of the global variables and since I am using C++ this does not seem to be an appropriate option (may be I am wrong)
My question is if I have a producer/consumer problem and I want to put both in separate classes, since they will be sharing data I would need to pass them the same mutex and queue now how do I share these two variables between them without defining it to be global and what is the best practice for creating threads?
Here is a working example of my basic code using global variables.
#include <iostream>
#include <thread>
#include <mutex>
#include <queue>
#include <condition_variable>
std::queue<int> buffer;
std::mutex mtx;
std::condition_variable cond;
const int MAX_BUFFER_SIZE = 50;
class Producer
{
public:
void run(int val)
{
while(true) {
std::unique_lock locker(mtx) ;
cond.wait(locker, []() {
return buffer.size() < MAX_BUFFER_SIZE;
});
buffer.push(val);
std::cout << "Produced " << val << std::endl;
val --;
locker.unlock();
// std::this_thread::sleep_for(std::chrono::seconds(2));
cond.notify_one();
}
}
};
class Consumer
{
public:
void run()
{
while(true) {
std::unique_lock locker(mtx);
cond.wait(locker, []() {
return buffer.size() > 0;
});
int val = buffer.front();
buffer.pop();
std::cout << "Consumed " << val << std::endl;
locker.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
cond.notify_one();
}
}
};
int main()
{
std::thread t1(&Producer::run, Producer(), MAX_BUFFER_SIZE);
std::thread t2(&Consumer::run, Consumer());
t1.join();
t2.join();
return 0;
}
Typically, you want to have synchronisation objects packaged alongside the resource(s) they are protecting.
A simple way to do that in your case would be a class that contains the buffer, the mutex, and the condition variable. All you really need is to share a reference to one of those to both the Consumer and the Producer.
Here's one way to go about it while keeping most of your code as-is:
class Channel {
std::queue<int> buffer;
std::mutex mtx;
std::condition_variable cond;
// Since we know `Consumer` and `Producer` are the only entities
// that will ever access buffer, mtx and cond, it's better to
// not provide *any* public (direct or indirect) interface to
// them, and use `friend` to grant access.
friend class Producer;
friend class Consumer;
public:
// ...
};
class Producer {
Channel* chan_;
public:
explicit Producer(Channel* chan) : chan_(chan) {}
// ...
};
class Consumer {
Channel* chan_;
public:
explicit Consumer(Channel* chan) : chan_(chan) {}
// ...
};
int main() {
Channel channel;
std::thread t1(&Producer::run, Producer(&channel), MAX_BUFFER_SIZE);
std::thread t2(&Consumer::run, Consumer(&channel));
t1.join();
t2.join();
}
However, (Thanks for the prompt, #Ext3h) a better way to go about this would be to encapsulate access to the synchronisation objects as well, i.e. keep them hidden in the class. At that point Channel becomes what is commonly known as a Synchronised Queue
Here's what I'd subjectively consider a nicer-looking implementation of your example code, with a few misc improvements thrown in as well:
#include <cassert>
#include <iostream>
#include <thread>
#include <mutex>
#include <queue>
#include <optional>
#include <condition_variable>
template<typename T>
class Channel {
static constexpr std::size_t default_max_length = 10;
public:
using value_type = T;
explicit Channel(std::size_t max_length = default_max_length)
: max_length_(max_length) {}
std::optional<value_type> next() {
std::unique_lock locker(mtx_);
cond_.wait(locker, [this]() {
return !buffer_.empty() || closed_;
});
if (buffer_.empty()) {
assert(closed_);
return std::nullopt;
}
value_type val = buffer_.front();
buffer_.pop();
cond_.notify_one();
return val;
}
void put(value_type val) {
std::unique_lock locker(mtx_);
cond_.wait(locker, [this]() {
return buffer_.size() < max_length_;
});
buffer_.push(std::move(val));
cond_.notify_one();
}
void close() {
std::scoped_lock locker(mtx_);
closed_ = true;
cond_.notify_all();
}
private:
std::size_t max_length_;
std::queue<value_type> buffer_;
bool closed_ = false;
std::mutex mtx_;
std::condition_variable cond_;
};
void producer_main(Channel<int>& chan, int val) {
// Don't use while(true), it's Undefined Behavior
while (val >= 0) {
chan.put(val);
std::cout << "Produced " << val << std::endl;
val--;
}
}
void consumer_main(Channel<int>& chan) {
bool running = true;
while (running) {
auto val = chan.next();
if (!val) {
running = false;
continue;
}
std::cout << "Consumed " << *val << std::endl;
};
}
int main()
{
// You are responsible for ensuring the channel outlives both threads.
Channel<int> channel;
std::thread producer_thread(producer_main, std::ref(channel), 13);
std::thread consumer_thread(consumer_main, std::ref(channel));
producer_thread.join();
channel.close();
consumer_thread.join();
return 0;
}

Print permutation of {0, 1, 2, 3} by multithread program (C++)

I want print a permutation of {0, 1, 2, 3} set by a multithread program written in C++11.
The source code is this:
#include <iostream>
#include <stdio.h>
#include <thread>
#include <vector>
#include <chrono>
using namespace std;
void func(int index);
int main()
{
vector<thread> threads;
for (int i = 0; i < 4; i++)
{
auto var = [&]()
{
return func(i);
};
threads.push_back(thread(var));
}
for (auto& thread : threads)
thread.join();
}
void func(int index)
{
cout << index;
for (int i = 0; i < 10000; i++);
}
I expect in output a permutation of 0123, but I receive weird results, like these:
0223
0133
0124
I don't understand this weird behaviour, in particualar I cannot explain the presence of number 4.
Probably this is a beginner's mistake, I thanks anyway everybody will help me.
You are capturing i by reference:
auto var = [&]()
{
return func(i);
};
As such, when the thread that gets eventually started gets kicked off and going, it does not have an actual copy, the value of i that it has at this moment, but it has only a reference to i.
Which was probably incremented, once or twice now. If you consider that a reference is really just an ordinary pointer with a thin layer of makeup on top of it, you should be able to figure this out on your own. The thread gets a pointer to i, which, who knows how many times it could've been incremented, by the time the thread gets going.
And, technically, since i could've even gone out of scope here, if the for loop terminated before the thread started executing, this is undefined behavior.
You're invoking undefined behaviors in three ways:
Firstly, you're capturing the value of a stack variable by reference rather than by value, so when the thread starts it will call the lambda and use the then-current value of i rather than the value at the time of capture.
[edit: No-longer true as of C++11] Second is the thread-safety of cout.
The third is an assumption of the order in which the threads execute which is not guaranteed. [edit:] This includes not only the order in which they start but in which they access cout to write their output.
But do you need to solve the order of execution?
If you do, then instead of passing the values to the threads, put them into a queue and give the threads access to the queue.
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <chrono>
#include <queue>
class LockedQueue {
std::queue<int> queue_;
mutable std::mutex mutex_;
public:
LockedQueue() = default;
// these don't have to be deleted, but you'd have to decide whether or
// not each operation needed to invoke a lock, and in the case of operator=
// you have two mutexes to contend with.
LockedQueue(const LockedQueue&) = delete;
LockedQueue(LockedQueue&&) = delete;
LockedQueue& operator=(const LockedQueue&) = delete;
LockedQueue& operator=(LockedQueue&&) = delete;
void push(int value) {
std::lock_guard<std::mutex> lock(mutex_);
queue_.push(value);
}
int pop() {
std::lock_guard<std::mutex> lock(mutex_);
int value = queue_.front();
queue_.pop();
return value;
}
bool empty() const {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.empty();
}
};
void func(LockedQueue& work, LockedQueue& results);
int main()
{
LockedQueue work, results;
std::vector<std::thread> threads;
for (int i = 0; i < 4; i++)
{
work.push(i);
threads.emplace_back(func, std::ref(work), std::ref(results));
}
for (auto& thread : threads)
thread.join();
while (!results.empty()) {
int i = results.pop();
std::cout << i;
}
}
void func(LockedQueue& work, LockedQueue& results)
{
int index = work.pop();
using namespace std::chrono_literals;
std::this_thread::sleep_for(1s);
results.push(index);
}
http://ideone.com/7G0JEO
We are still not guaranteed to get our results back in-order: it's quite possible that the thread that takes 0 off the queue is then pre-empted and doesn't execute again until 1, 2 and 3 have had their results pushed onto the result queue.
As Sam Varshavchik mentioned about the undefined behavior of the i when it when it goes out of scope, i suggest to join each thread created inside the loop where i exists by adding this :
threads[i].join();
And don't forget to remove the :
for (auto& thread : threads)
thread.join();
Your main function should be like this :
int main()
{
vector<thread> threads;
for (int i = 0; i < 4; i++)
{
auto var = [&]()
{
return func(i);
};
threads.push_back(thread(var));
threads[i].join(); // joining the thread after its creation.
}
system("pause");
return 0;
}
Amrane Abdelkader.

C++ Concurrency segfault on mutex

Hello,
i am quite new to C++ but I have 6 years Java experience, 2 years C experience and some knowledge of concurrency basics. I am trying to create a threadpool to handle tasks. it is below with the associated test main.
it seems like the error is generated from
void ThreadPool::ThreadHandler::enqueueTask(void (*task)(void)) {
std::lock_guard<std::mutex> lock(queueMutex);
as said by my debugger, but doing traditional cout debug, i found out that sometimes it works without segfaulting and removing
threads.emplace(handler->getSize(), handler);
from ThreadPool::enqueueTask() improves stability greatly.
Overall i think it is related too my bad use of condition_variable (called idler).
compiler: minGW-w64 in CLion
.cpp
#include <iostream>
#include "ThreadPool.h"
ThreadPool::ThreadHandler::ThreadHandler(ThreadPool *parent) : parent(parent) {
thread = std::thread([&]{
while (this->parent->alive){
if (getSize()){
std::lock_guard<std::mutex> lock(queueMutex);
(*(queue.front()))();
queue.pop_front();
} else {
std::unique_lock<std::mutex> lock(idlerMutex);
idler.wait(lock);
}
}
});
}
void ThreadPool::ThreadHandler::enqueueTask(void (*task)(void)) {
std::lock_guard<std::mutex> lock(queueMutex);
queue.push_back(task);
idler.notify_all();
}
size_t ThreadPool::ThreadHandler::getSize() {
std::lock_guard<std::mutex> lock(queueMutex);
return queue.size();
}
void ThreadPool::enqueueTask(void (*task)(void)) {
std::lock_guard<std::mutex> lock(threadsMutex);
std::map<int, ThreadHandler*>::iterator iter = threads.begin();
threads.erase(iter);
ThreadHandler *handler = iter->second;
handler->enqueueTask(task);
threads.emplace(handler->getSize(), handler);
}
ThreadPool::ThreadPool(size_t size) {
for (size_t i = 0; i < size; ++i) {
std::lock_guard<std::mutex> lock(threadsMutex);
ThreadHandler *handler = new ThreadHandler(this);
threads.emplace(handler->getSize(), handler);
}
}
ThreadPool::~ThreadPool() {
std::lock_guard<std::mutex> lock(threadsMutex);
auto it = threads.begin(), end = threads.end();
for (; it != end; ++it) {
delete it->second;
}
}
.h
#ifndef WLIB_THREADPOOL_H
#define WLIB_THREADPOOL_H
#include <mutex>
#include <thread>
#include <list>
#include <map>
#include <condition_variable>
class ThreadPool {
private:
class ThreadHandler {
std::condition_variable idler;
std::mutex idlerMutex;
std::mutex queueMutex;
std::thread thread;
std::list<void (*)(void)> queue;
ThreadPool *parent;
public:
ThreadHandler(ThreadPool *parent);
void enqueueTask(void (*task)(void));
size_t getSize();
};
std::multimap<int, ThreadHandler*> threads;
std::mutex threadsMutex;
public:
bool alive = true;
ThreadPool(size_t size);
~ThreadPool();
virtual void enqueueTask(void (*task)(void));
};
#endif //WLIB_THREADPOOL_H
main:
#include <iostream>
#include <ThreadPool.h>
ThreadPool pool(3);
void fn() {
std::cout << std::this_thread::get_id() << '\n';
pool.enqueueTask(fn);
};
int main() {
std::cout << "Hello, World!" << std::endl;
pool.enqueueTask(fn);
return 0;
}
Your main() function invokes enqueueTask().
Immediately afterwards, your main() returns.
This gets the gears in motion for winding down your process. This involves invoking the destructors of all global objects.
ThreadPool's destructor then proceeds to delete all dynamically-scoped threads.
While the threads are still running. Hilarity ensues.
You need to implement the process for an orderly shutdown of all threads.
This means setting active to false, kicking all of the threads in the shins, and then joining all threads, before letting nature take its course, and finally destroy everything.
P.S. -- you need to fix how alive is being checked. You also need to make access to alive thread-safe, protected by a mutex. The problem is that the thread could be holding a lock on one of two differented mutexes. This makes this process somewhat complicated. Some redesign is in order, here.

Accessing counter from two threads

I have a counter that is being incremented from one thread. In the main thread, I basically print it out by calling data member of a class. In the below code, nothing is being printed out.
#include <iostream>
#include <thread>
#include <windows.h>
#include <mutex>
std::mutex mut;
class Foo
{
public:
Foo(const int& m) : m_delay(m), m_count(0)
{}
void update()
{
std::cout << "count: " << this->m_count << std::endl;
}
void operator()()
{
while (true){
mut.lock();
m_count++;
mut.unlock();
Sleep(m_delay);
}
}
private:
int m_delay;
int m_count;
};
Foo *obj = new Foo(200);
int main()
{
std::thread *t = new std::thread(*obj);
t->join();
while(true)
{
obj->update();
Sleep(10);
}
return 0;
}
The problem with the original code is that this copies the Foo object:
std::thread *t = new std::thread(*obj);
That means that the increments happen to the copy, and so the value in the original Foo never changes, and so when main prints it out (if you move the misplaced join()) the value is always the same.
A solution is to use a reference not a copy:
std::thread *t = new std::thread(std::ref(*obj));
You also need to protect the read of the variable by the mutex (or use std::atomic<int> for the counter) to avoid undefined behaviour caused by concurrently reading and writing a non-atomic variable.
You should also stop using mut.lock() and mut.unlock() directly, use a scoped lock instead.
There's also no need to create things on the heap unnecessarily, overusing new is a bad habit of people who learnt Java and C# first.
You can also make the code portable by replacing the Windows-specific Sleep call with standard C++.
A correct version would be:
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
std::mutex mut;
class Foo
{
public:
Foo(std::chrono::milliseconds m) : m_delay(m), m_count(0)
{}
void update()
{
int count = 0;
{
std::lock_guard<std::mutex> lock(mut);
count = m_count;
}
std::cout << "count: " << count << std::endl;
}
void operator()()
{
while (true)
{
{
std::lock_guard<std::mutex> lock(mut);
m_count++;
}
std::this_thread::sleep_for(m_delay);
}
}
private:
std::chrono::milliseconds m_delay;
int m_count;
};
Foo obj(std::chrono::milliseconds(200));
int main()
{
std::thread t(std::ref(obj));
while(true)
{
obj.update();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
t.join();
return 0;
}
Alternatively, use an atomic variable so you don't need the mutex:
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
class Foo
{
public:
Foo(std::chrono::milliseconds m) : m_delay(m), m_count(0)
{}
void update()
{
std::cout << "count: " << m_count << std::endl;
}
void operator()()
{
while (true)
{
m_count++;
std::this_thread::sleep_for(m_delay);
}
}
private:
std::chrono::milliseconds m_delay;
std::atomic<int> m_count;
};
Foo obj(std::chrono::milliseconds(200));
int main()
{
std::thread t(std::ref(obj));
while(true)
{
obj.update();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
t.join();
return 0;
}