This is my minimal, reproducible example
#include <memory>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
class BaseClass {
public:
void do_func() {
while(true) {
std::cout << "doing stuff" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
};
int main() {
auto obj = std::make_unique<BaseClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "reset called!" << std::endl;
obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
return 0;
}
I was expecting the object to be deleted after reset is called. Even the code cannot exit because the while loop is blocking, which is understandable. I need to delete the object after a particular event, and cannot wait till the unique_ptr goes out of scope. If I change the do_func to
void do_func() {
std::cout << "doing stuff" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(20));
}
then it is the expected behaviour.
Edit:
Based on your comments I have updated my code to
#include <memory>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
class BaseClass {
public:
BaseClass() : x(1) {
dummy = std::make_shared<SomeClass>();
}
void do_func() {
while(true) {
std::cout << "doing stuff " << dummy->do_stuff(x) << std::endl;
x++;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
private:
int x;
class SomeClass {
public:
int do_stuff(int x) {
return x * x;
}
};
std::shared_ptr<SomeClass> dummy;
};
int main() {
auto obj = std::make_unique<BaseClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "reset called!" << std::endl;
obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
return 0;
}
And now the function does print garbage values. Does that mean I need to explicitly delete dummy in the destructor?
The simplest way to synchronize these two threads would be to use std::atomic_bool
#include <atomic>
class BaseClass {
public:
std::atomic_bool shouldContinueWork = true;
void do_func() {
while(shouldContinueWork) {
std::cout << "doing stuff" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
};
int main() {
auto obj = std::make_unique<BaseClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
obj->shouldContinueWork = false; //the thread will not do anything more after this, but the sleep will need to end on it's own
std::cout << "stopping work!" << std::endl;
// do not remove the object before join is called - you don't know if it will be still accessed from the other thread or not
// obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
// here it is safe to remove the `obj`, main thread is surely the only thread that accesses it
// (but it goes out of scope anyway)
return 0;
}
This solution doesn't take into account stopping the work midway (i.e. whole loop iteration must always be performed) and is generally prone to having a few more or less iterations of work - it should be precise enough when you have sleep of 1s, but with smaller sleep it won't guarantee any exact number of iterations, take that into account. std::condition_variable can be used for more precise control of thread synchronization.
Thanks for all your quick responses! Let me know if this is a good solution
#include <memory>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
class BaseClass {
public:
BaseClass() : x(1) {
dummy = std::make_shared<SomeClass>();
}
virtual ~BaseClass() {
dummy.reset();
}
void do_func() {
while(dummy) {
std::cout << "doing stuff " << dummy->do_stuff(x) << std::endl;
x++;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
private:
int x;
class SomeClass {
public:
int do_stuff(int x) {
return x * x;
}
};
std::shared_ptr<SomeClass> dummy;
};
class DerivedClass : public BaseClass {
};
int main() {
auto obj = std::make_unique<DerivedClass>();
std::thread t(&BaseClass::do_func, obj.get());
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "reset called!" << std::endl;
obj.reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "going out of scope" << std::endl;
t.join();
return 0;
}
The behaviour is now as expected.
Related
Consider this simple synchronization problem. I have two threads, A and B, that each execute 2 steps. I want step 1a to be performed before step 2b.
Thread A
Thread B
Step 1a
Step 1b
Step 2a
Step 2b
I have some options for how to implement this.
std::condition_variable + std::mutex + bool
This is the solution proposed by this stack overflow answer and this leetcode discussion page.
Thread B will wait on the condition variable, and Thread A will notify the condition variable. The mutex is required because it is the argument of the condition_variable's wait.
#include <iostream>
#include <thread>
#include <condition_variable>
std::condition_variable step_1a;
std::mutex a_mutex_I_guess;
bool step_1a_done = false;
void Step_1a() {
std::cout << "step 1a" << "\n";
}
void Step_2a() {
std::cout << "step 2a" << "\n";
}
void Step_1b() {
std::cout << "step 1b" << "\n";
}
void Step_2b() {
std::cout << "step 2b" << "\n";
}
void A() {
//std::unique_lock<std::mutex> lck{ a_mutex_I_guess }; unnecessary
Step_1a();
step_1a_done = true;
//lck.unlock(); unnecessary
step_1a.notify_one();
Step_2a();
}
void B() {
Step_1b();
std::unique_lock<std::mutex> lck{ a_mutex_I_guess };
step_1a.wait(lck, []() { return step_1a_done; });
Step_2b();
}
int main() {
std::thread thread_A{ A };
std::thread thread_B{ B };
thread_A.join();
thread_B.join();
}
To me, this seems like overkill. std::condition_variables are designed to handle multiple waiting threads. std::mutex is intended to protect shared data, not to be fodder for wait. On top of all of that, I needed bool step_1a_done to actually keep track of whether or not step_1a had completed.
As a measure of their complexity, the mutex, condition_variable, and bool together require 153 (80 + 72 + 1) bytes of memory on my machine.
std::binary_semaphore
Alternatively, I can use a binary semaphore. Semantically, the binary semaphore isn't meant for one-time-use. However, it gets the job done with simpler tools than the previous option.
#include <iostream>
#include <thread>
#include <semaphore>
std::binary_semaphore step_1a_sem{ 0 };
void Step_1a() {
std::cout << "step 1a" << "\n";
}
void Step_2a() {
std::cout << "step 2a" << "\n";
}
void Step_1b() {
std::cout << "step 1b" << "\n";
}
void Step_2b() {
std::cout << "step 2b" << "\n";
}
void A() {
//std::unique_lock<std::mutex> lck{ a_mutex_I_guess }; unnecessary
Step_1a();
step_1a_sem.release();
Step_2a();
}
void B() {
Step_1b();
step_1a_sem.acquire();
Step_2b();
}
int main() {
std::thread thread_A{ A };
std::thread thread_B{ B };
thread_A.join();
thread_B.join();
}
step_1a_sem requires only 1 byte of memory.
Question
My assessment is that binary_semaphore is better. However, even better would be a "one_time_semaphore" that documents (or enforces) in my code that release should only be called once. Are there C++ concurrency primitives that are a better fit for this thread synchronization problem?
EDIT: std::promise<void>
#Daniel Langr has pointed out that std::promise<void> also works. While this seems like the exact use case of std::promise<void>, things appear significantly more complicated under the hood than with a binary_semaphore. The memory requirement is 24 bytes.
#include <iostream>
#include <thread>
#include <future>
std::promise<void> step_1a_done;
void Step_1a() {
std::cout << "step 1a" << "\n";
}
void Step_2a() {
std::cout << "step 2a" << "\n";
}
void Step_1b() {
std::cout << "step 1b" << "\n";
}
void Step_2b() {
std::cout << "step 2b" << "\n";
}
void A() {
Step_1a();
step_1a_done.set_value();
Step_2a();
}
void B() {
Step_1b();
step_1a_done.get_future().wait();
Step_2b();
}
int main() {
std::thread thread_A{ A };
std::thread thread_B{ B };
thread_A.join();
thread_B.join();
}
I'm getting a crash when calling interrupt() on an outer boost::thread, which runs an inner boost::thread, which is connected to a thread_guard. It's not crashing when calling join() manually on the inner thread.
Crash:
terminate called after throwing an instance of 'boost::thread_interrupted'
Source:
https://gist.github.com/elsamuko/6e178c37fa2cf8742cb6bf512f2ff866
#include <iostream>
#include <thread>
#include <boost/thread/thread.hpp>
#include <boost/thread/thread_guard.hpp>
#define LOG( A ) std::cout << A << std::endl;
void double_interrupt() {
boost::thread outer([] {
boost::thread inner([]{
while(true) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
});
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
LOG("Interrupting inner");
boost::thread_guard<boost::join_if_joinable> guard(inner); // crashes
// inner.join(); // works
}
});
LOG("Interrupting outer");
outer.interrupt();
outer.join();
}
int main(int argc, char* argv[]) {
LOG("Start");
double_interrupt();
LOG("End");
return 0;
}
Compile & Run:
http://coliru.stacked-crooked.com/a/46c512bf9a385fff
I'm running on Ubuntu 18.04. with g++ 7.5.0 and got the latest boost 1.78.0.
I opened this issue on github, too: https://github.com/boostorg/thread/issues/366
You're mixing std::thread and boost::thread.
Only Boost Thread knows about interruption points. Use that to fix:
Live On Coliru
#include <iostream>
#include <thread>
#include <boost/thread.hpp>
#include <boost/thread/thread_guard.hpp>
void double_interrupt() {
boost::thread outer([] {
boost::thread inner([] {
while (true) {
boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
}
});
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
std::cout << "Interrupting inner" << std::endl;
boost::thread_guard<boost::join_if_joinable> guard(inner);
}
});
std::cout << "Interrupting outer" << std::endl;
outer.interrupt();
outer.join();
}
int main() {
std::cout << "Start" << std::endl;
double_interrupt();
std::cout << "End" << std::endl;
}
Prints
Start
Interrupting outer
End
I got a solution. The problem was, that the join() of the thread_guard waits for the inner thread with a condition_variable::wait(). condition_variable::wait() itself checks, if it's interruptible and throws an exception.
The solution is to use a custom thread_guard with disable_interruption:
#include <iostream>
#include <thread>
#include <boost/thread.hpp>
#include <boost/thread/thread_guard.hpp>
#define LOG( A ) std::cout << A << std::endl;
void work() {
size_t sum = 0;
for(int i = 0; i < 1E7; ++i) { sum += 1; }
LOG("work: " << sum);
}
// helper struct to interrupt a boost::thread within a boost::thread
struct non_interruptable_interrupt_and_join_if_joinable {
template <class Thread>
void operator()(Thread& t) {
if(t.joinable()) {
boost::this_thread::disable_interruption di;
t.interrupt();
t.join();
}
}
};
void double_interrupt() {
boost::thread outer([] {
boost::thread inner([] {
while(true) {
boost::this_thread::interruption_point();
work();
}
});
{
boost::thread_guard<non_interruptable_interrupt_and_join_if_joinable> guard(inner);
LOG("Interrupting inner");
}
});
LOG("Interrupting outer");
outer.interrupt();
outer.join();
}
int main() {
LOG("Start");
double_interrupt();
LOG("End");
}
Run here:
http://coliru.stacked-crooked.com/a/a365e40a2bd574cc
I can't close my thread. Am I forgetting to do something? The thread seems like it's saving the value I'm using for close, and then never checks if it has changed. Here is some example code that has an identical effect:
#include "stdafx.h"
#include "Windows.h"
#include <iostream>
#include <thread>
class test {
private:
bool user_wants_thread = true;
bool time_to_close = false;
public:
bool set_timetoclose(bool in) {
time_to_close = in;
if (time_to_close == in) {
return true;
}
return false;
}
void function() {
while (user_wants_thread) {
// CODE
std::cout << time_to_close;
Sleep(100);
if (time_to_close) {
goto close;
}
}
close:
Sleep(1);
}
};
int main() {
test t;
std::thread thread_func(&test::function, t);
Sleep(1000);
bool success;
do {
success = t.set_timetoclose(true);
} while (!success);
thread_func.join();
std::cout << "Closed";
std::cin.get();
}
I removed some unused parts and changed the actual condition to be an atomic<bool> and it seems to work as shown on this link:
http://rextester.com/TWHK12491
I'm not claiming this is absolutely correct, however, but it shows how using the atomic causes synchronization across reads/writes to the value which could result in a data race.
#include "Windows.h"
#include <iostream>
#include <thread>
#include <atomic>
class test {
public:
std::atomic<bool> time_to_close = false;
test()=default;
void function() {
while (!time_to_close) {
std::cout << "Running..." << std::endl;
Sleep(100);
}
std::cout << "closing" << std::endl;
}
};
int main() {
test t;
std::thread thread_func([&t](){t.function();});
Sleep(500);
t.time_to_close = true;
std::cout << "Joining on thread" << std::endl;
thread_func.join();
std::cout << "Closed";
return 0;
}
I'm using Boost::thread to implement an InterruptibleThread class, while getting segmentation fault during execution. Any idea?
The source and the output are under below.
interruptiblethread.h
#ifndef INTERRUPTIBLETHREAD_H
#define INTERRUPTIBLETHREAD_H
#include <boost/thread.hpp>
#include <boost/thread/future.hpp>
#include <boost/thread/tss.hpp>
class InterruptFlag
{
public:
inline void set()
{
boost::lock_guard<boost::mutex> guard(_mtx);
_set = true;
}
inline bool is_set()
{
std::cout << "is_set()" << std::endl;
boost::lock_guard<boost::mutex> guard(_mtx);
std::cout << "is_set() end" << std::endl;
return _set;
}
private:
boost::mutex _mtx;
bool _set;
};
extern boost::thread_specific_ptr<InterruptFlag> this_thread_interrupt_flag;
class InterruptibleThread
{
public:
template<typename FunctionType>
InterruptibleThread(FunctionType f)
{
boost::promise<InterruptFlag*> p;
_internal_thread = boost::thread([f, &p]()
{
p.set_value(this_thread_interrupt_flag.get());
f();
});
_interrupt_flag = p.get_future().get();
}
inline void interrupt()
{
if (_interrupt_flag != nullptr)
{
_interrupt_flag->set();
}
}
private:
boost::thread _internal_thread;
InterruptFlag* _interrupt_flag;
};
#endif // INTERRUPTIBLETHREAD_H
interruptiblethread.cpp
#include <iostream>
#include <functional>
#include "interruptiblethread.h"
using std::cout; using std::endl;
using std::function;
boost::thread_specific_ptr<InterruptFlag> this_thread_interrupt_flag;
struct thread_interrupted {};
void interruption_point()
{
cout << "interruption_point()" << endl;
if (this_thread_interrupt_flag->is_set())
{
cout << "is_set" << endl;
throw thread_interrupted();
}
}
void foo()
{
while (true)
{
cout << "iterate" << endl;
try
{
interruption_point();
} catch (const thread_interrupted& interrupt)
{
cout << "catch thread_interrupted" << endl;
break;
}
}
}
int main()
{
InterruptibleThread int_thread(foo);
int_thread.interrupt();
while (true) {}
}
Output:
➜ build ./main
iterate
interruption_point()
is_set()
[1] 44435 segmentation fault ./main
this_thread_interrupt_flag is not initialized. Please initialize it correctly as described here
Your call to is_set is UB.
I am playing around with some sockets, thread and mutexes. My question concerns threads and mutexes:
int ConnectionHandler::addNewSocket(){
this->connectionList_mutex.lock();
std::cout << "test1" << std::endl;
this->connectionList_mutex.unlock();
return 0;
}
int ConnectionHandler::main(){
while(true){
this->connectionList_mutex.lock();
std::cout << "test2" << std::endl;
this->connectionList_mutex.unlock();
}
}`
The main function is running in one thread, while the addNewSocket is called by another thread. The problem is, that when addNewSocket is called once (by the second thread), the next unlock by thread 1 (main) will fail with a strange "signal SIGABRT". I have worked two days on this now, but i did not manage to get it fixed, sadly. I hope you can help me.
Edit: ConnectionHandler is a class, that has connectionList_mutex as a member.
Edit: Sometimes i also get this error: "Assertion failed: (ec == 0), function unlock, file /SourceCache/libcxx/libcxx-65.1/src/mutex.cpp, line 44." but it occurs randomly.
Edit: This is the whole class (Reduced to a minimum, should be context independant to a certain degree, but crashes when i put it right after a client connected, and works if i put it right after the start:
class ConnectionHandler{
public:
ConnectionHandler();
int addNewSocket();
private:
int main();
static void start(void * pThis);
std::mutex connectionList_mutex;
};
ConnectionHandler::ConnectionHandler(){
std::thread t(&this->start, this);
t.detach();
}
void ConnectionHandler::start(void * pThis){
ConnectionHandler *handlerThis;
handlerThis = (ConnectionHandler *)pThis;
handlerThis->main();
}
int ConnectionHandler::addNewSocket(){
this->connectionList_mutex.lock();
std::cout << "test1" << std::endl;
this->connectionList_mutex.unlock();
return 0;
}
int ConnectionHandler::main(){
while(true){
this->connectionList_mutex.lock();
std::cout << "test2" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
this->connectionList_mutex.unlock();
}
}
My guess is that your ConnectionHandler object is being destroyed somewhere. Also, you have defined ConnectionHandler::start in a silly way.
First, ConnectionHandler::start should be defined this way:
void ConnectionHandler::start(ConnectionHandler * pThis){
pThis->main();
}
The C++11 ::std::thread class is perfectly capable of preserving the type of the function argument so there is no need to resort to void *.
Secondly, add in this code:
void ConnectionHandler::~ConnectionHandler(){
const void * const meptr = this;
this->connectionList_mutex.lock();
::std::cout << "ConnectionHandler being destroyed at " << meptr << ::std::endl;
this->connectionList_mutex.unlock();
}
And change the constructor to read:
ConnectionHandler::ConnectionHandler(){
const void * const meptr = this;
::std::cout << "ConnectionHandler being created at " << meptr << ::std::endl;
std::thread t(&this->start, this);
t.detach();
}
This will show you when the ConnectionHandler object is being destroyed. And my guess is that your code is destroying it while your detached thread is still running.
The meptr thing is because operator << has an overload for void * that prints out the pointer value. Printing out the pointer value for this will allow you to match up calls to the constructor and destructor if you're creating multiple ConnectionHandler objects.
Edit: Since it turned out I was correct, here is how I would recommend you write the play ConnectionHandler class:
#include <iostream>
#include <atomic>
#include <thread>
#include <chrono>
#include <mutex>
class ConnectionHandler {
public:
ConnectionHandler();
~ConnectionHandler();
ConnectionHandler(const ConnectionHandler &) = delete;
const ConnectionHandler &operator =(const ConnectionHandler &) = delete;
int addNewSocket();
private:
int main();
static void start(ConnectionHandler * pThis);
::std::mutex connectionList_mutex;
volatile ::std::atomic_bool thread_shutdown;
::std::thread thread;
};
ConnectionHandler::ConnectionHandler()
: thread_shutdown(false), thread(&this->start, this)
{
}
ConnectionHandler::~ConnectionHandler()
{
thread_shutdown.store(true);
thread.join();
}
void ConnectionHandler::start(ConnectionHandler * pThis){
pThis->main();
}
int ConnectionHandler::addNewSocket(){
::std::lock_guard< ::std::mutex> lock(connectionList_mutex);
::std::cout << "test1" << ::std::endl;
return 0;
}
int ConnectionHandler::main(){
while(!thread_shutdown.load()){
::std::lock_guard< ::std::mutex> lock(connectionList_mutex);
::std::cout << "test2" << ::std::endl;
::std::this_thread::sleep_for(::std::chrono::milliseconds(100));
}
return 0;
}