How to join a std::thread from itself (in C++11) - c++

I have a std::thread waiting and reading from a socket. And there is a pointer to this thread stored somewhere. But when something bad happens and the thread ends, I want it to call something that results in a function that will join this thread and then delete the pointer referring to it. (I have access to that pointer from within the thread)
I could do that in another thread but then that new thread becomes the problem.

You could create your thread in a detached state, and make your thread lifetime dependent a condition variable and switch a boolean state on finish.
#include <thread>
#include <iostream>
#include <unistd.h>
#include <condition_variable>
#include <mutex>
class A {
private:
void Threadfunction();
volatile bool class_running;
volatile bool thread_running;
std::condition_variable cv;
std::mutex mu;
public:
A();
~A();
void Stop();
};
A::A(){
class_running = true;
thread_running = false;
std::thread t(&A::Threadfunction,this);
t.detach();
}
A::~A(){
if(class_running) {this->Stop();}
}
void A::Stop() {
std::unique_lock<std::mutex> lk(mu);
class_running = false;
while(thread_running) {
cv.wait(lk);
}
std::cout << "Stop ended " << std::endl;
}
void A::Threadfunction(){
thread_running = true;
std::cout << "thread started " << std::endl;
while(class_running){
// Do something
}
thread_running = false;
cv.notify_one();
std::cout << "thread stopped " << std::endl;
}
int main(){
A a1;
A a2;
sleep(1);
std::cout << "a1.Stop() called " << std::endl;
a1.Stop();
sleep(1);
std::cout << "a2.Stop() not called but a2 goes out of scope and destructor is called " << std::endl;
}

Change your design so that you don't have this bizarre requirement. One simple solution is to use shared_ptrs to a control structure that owns the thread and has other status information as well. The thread can hold a shared_ptr to this control structure and use it to report its status to any other interested code. When nobody cares about this thread anymore, the last shared_ptr to this control structure will go away and it will be destroyed.

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;
}

C++ Which thread calls the destructor

If I create a thread_local object, its destructor is called on the thread it was created on:
#include <iostream>
#include <thread>
#include <chrono>
struct MyStruct {
~MyStruct() {
std::cout << "Destructed on thread #" << std::this_thread::get_id() << std::endl;
}
};
void f() {
thread_local MyStruct myStruct;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main() {
std::thread t(f);
std::cout << "Created thread #" << t.get_id() << std::endl;
t.join();
}
Created thread #16920
Destructed on thread #16920
Does the C++ standard guarantee this behaviour? It only states this:
A variable with thread storage duration shall be initialized before
its first odr-use (6.2) and, if constructed, shall be destroyed on
thread exit.

Modify shared state and notify std::condition_variable if std::mutex::lock throws

I encountered some problem and I'm not sure how to deal with it.
#include <iostream>
#include <thread>
#include <condition_variable>
#include <chrono>
std::condition_variable CV;
std::mutex m;
std::size_t i{0};
void set_value() try
{
std::this_thread::sleep_for(std::chrono::seconds{2});
{
std::lock_guard<std::mutex> lock{m};
i = 20;
}
CV.notify_one();
}
catch(...){
//what to do?
}
int main()
{
std::thread t{set_value};
t.detach();
std::unique_lock<std::mutex> lock{m};
CV.wait(lock, []{ return i != 0; });
std::cout << "i has changed to " << i << std::endl;
}
This of course works fine but how should I handle the case when std::lock_guard::lock throws an exception?
At first I was thinking to create global std::atomic<bool> mutex_lock_throwed{ false }; that I could set to true inside the catch block. Than I could notify_one()
catch(...){
mutex_lock_throwed.store(true);
CV.notify_one();
}
and change predicate for wait function to
[]{ return i != 0 || mutex_lock_throwed.load(); }
This actually worked very well but I read this in cppreference
Even if the shared variable is atomic, it must be modified under the mutex in order to correctly publish the modification to the waiting thread.
As you can see its not possible if mutex throws. So what should be the correct way to handle this?

Stopping boost::asio::io_service::run() from concurrent destructor

Can anybody explain me why this program does not terminate (see the comments)?
#include <boost/asio/io_service.hpp>
#include <boost/asio.hpp>
#include <memory>
#include <cstdio>
#include <iostream>
#include <future>
class Service {
public:
~Service() {
std::cout << "Destroying...\n";
io_service.post([this]() {
std::cout << "clean and stop\n"; // does not get called
// do some cleanup
// ...
io_service.stop();
std::cout << "Bye!\n";
});
std::cout << "...destroyed\n"; // last printed line, blocks
}
void operator()() {
io_service.run();
std::cout << "run completed\n";
}
private:
boost::asio::io_service io_service;
boost::asio::io_service::work work{io_service};
};
struct Test {
void start() {
f = std::async(std::launch::async, [this]() { service(); std::cout << "exiting thread\n";});
}
std::future<void> f;
Service service;
};
int main(int argc, char* argv[]) {
{
Test test;
test.start();
std::string exit;
std::cin >> exit;
}
std::cout << "exiting program\n"; // never printed
}
The real issue is that destruction of io_service is (obviously) not thread-safe.
Just reset the work and join the thread. Optionally, set a flag so your IO operations know shutdown is in progress.
You Test and Service classes are trying to share responsibility for the IO service, that doesn't work. Here's much simplified, merging the classes and dropping the unused future.
Live On Coliru
The trick was to make the work object optional<>:
#include <boost/asio.hpp>
#include <boost/optional.hpp>
#include <iostream>
#include <thread>
struct Service {
~Service() {
std::cout << "clean and stop\n";
io_service.post([this]() {
work.reset(); // let io_service run out of work
});
if (worker.joinable())
worker.join();
}
void start() {
assert(!worker.joinable());
worker = std::thread([this] { io_service.run(); std::cout << "exiting thread\n";});
}
private:
boost::asio::io_service io_service;
std::thread worker;
boost::optional<boost::asio::io_service::work> work{io_service};
};
int main() {
{
Service test;
test.start();
std::cin.ignore(1024, '\n');
std::cout << "Start shutdown\n";
}
std::cout << "exiting program\n"; // never printed
}
Prints
Start shutdown
clean and stop
exiting thread
exiting program
See here: boost::asio hangs in resolver service destructor after throwing out of io_service::run()
I think the trick here is to destroy the worker (the work member) before calling io_service.stop(). I.e. in this case the work could be an unique_ptr, and call reset() explicitly before stopping the service.
EDIT: The above helped me some time ago in my case, where the ioservice::stop didn't stop and was waiting for some dispatching events which never happened.
However I reproduced the problem you have on my machine and this seems to be a race condition inside ioservice, a race between ioservice::post() and the ioservice destruction code (shutdown_service). In particular, if the shutdown_service() is triggered before the post() notification wakes up the other thread, the shutdown_service() code removes the operation from the queue (and "destroys" it instead of calling it), therefore the lambda is never called then.
For now it seems to me that you'd need to call the io_service.stop() directly in the destructor, not postponed via the post() as that apparently doest not work here because of the race.
I was able to fix the problem by rewriting your code like so:
class Service {
public:
~Service() {
std::cout << "Destroying...\n";
work.reset();
std::cout << "...destroyed\n"; // last printed line, blocks
}
void operator()() {
io_service.run();
std::cout << "run completed\n";
}
private:
boost::asio::io_service io_service;
std::unique_ptr<boost::asio::io_service::work> work = std::make_unique<boost::asio::io_service::work>(io_service);
};
However, this is largely a bandaid solution.
The problem lies in your design ethos; specifically, in choosing not to tie the lifetime of the executing thread directly to the io_service object:
struct Test {
void start() {
f = std::async(std::launch::async, [this]() { service(); std::cout << "exiting thread\n";});
}
std::future<void> f; //Constructed First, deleted last
Service service; //Constructed second, deleted first
};
In this particular scenario, the thread is going to continue to attempt to execute io_service.run() past the lifetime of the io_service object itself. If more than the basic work object were executing on the service, you very quickly begin to deal with undefined behavior with calling member functions of deleted objects.
You could reverse the order of the member objects in Test:
struct Test {
void start() {
f = std::async(std::launch::async, [this]() { service(); std::cout << "exiting thread\n";});
}
Service service;
std::future<void> f;
};
But it still represents a significant design flaw.
The way that I usually implement anything which uses io_service is to tie its lifetime to the threads that are actually going to be executing on it.
class Service {
public:
Service(size_t num_of_threads = 1) :
work(std::make_unique<boost::asio::io_service::work>(io_service))
{
for (size_t thread_index = 0; thread_index < num_of_threads; thread_index++) {
threads.emplace_back([this] {io_service.run(); });
}
}
~Service() {
work.reset();
for (std::thread & thread : threads)
thread.join();
}
private:
boost::asio::io_service io_service;
std::unique_ptr<boost::asio::io_service::work> work;
std::vector<std::thread> threads;
};
Now, if you have any infinite loops active on any of these threads, you'll still need to make sure you properly clean those up, but at least the code specific to the operation of this io_service is cleaned up correctly.

What is a valid way to stop a std::thread by an external signal?

This is a code which works not as designed please explain me what is wrong here (code simplified to make this more readable).
shm_server server;
std::thread s{server};
// some work...
std::cout << "press any key to stop the server";
_getch();
server.stop();
s.join();
It looks like I call a stop method for another copy of shm_server class.
because stop() only sets std::atomic_bool done; (shm_server member) to true but I see that thread function (this is operator() of shm_server) still sees done equal to false.
std::thread has only move contructor?
How to send a signal to server correctly in this typical case?
class shm_server {
std::atomic_bool done;
public:
shm_server() : done{false} {}
shm_server(shm_server& ) : done{false} {}
void operator()() {
while (!done) {
//...
}
}
void stop() {
done = true;
}
};
You have somehow shot yourself into the foot by making shm_server copyable. I believe you did this in order to get rid of the compiler error, not because copy semantics on that class are particularly useful. I'd recommend you delete that constructor again. If you really want copy semantics, have the constructor take its argument by reference to const.
class shm_server // cannot copy or move
{
std::atomic_bool done_ {};
public:
void
operator()()
{
this->run();
}
void
run()
{
using namespace std::chrono_literals;
while (!this->done_.load())
{
std::clog << std::this_thread::get_id() << " working..." << std::endl;
std::this_thread::sleep_for(1ms);
}
}
void
stop()
{
this->done_.store(true);
}
};
I have factored out the logic of the call operator into a named function for convenience. You don't need to do that but I'll use it later in the example.
Now we somehow have to make the run member function be executed on its own thread. If you write
shm_server server {};
std::thread worker {server}; // won't compile
the compiler won't let you do it as it – as you have conjectured yourself – would attempt to copy the server object which isn't copyable.
#Ben Voigt has suggested to wrap the server object into a std::reference_wrapper which is an object that behaves like a reference.
shm_server server {};
std::thread worker {std::ref(server)};
This works as intended and effectively passes a pointer to the std::thread constructor, rather than the actual server object.
However, I find that this is not the most straight-forward solution here. What you really want to do is run a member function of your server on a different thread. And std::thread's constructor lets you do just that.
shm_server server {};
std::thread worker {&shm_server::run, &server};
Here, I'm passing the address of the run member function and a pointer to the server object (that will be passed as the implicit this pointer) as argument. I have introduced the run function since the syntax might be less irritating. You can also pass the address of the call operator directly.
shm_server server {};
std::thread worker {&shm_server::operator(), &server};
Here is a complete example.
int
main()
{
using namespace std::chrono_literals;
std::clog << std::this_thread::get_id() << " starting up" << std::endl;
shm_server server {};
std::thread worker {&shm_server::operator(), &server};
//std::thread worker {std::ref(server)}; // same effect
//std::thread worker {&shm_server::run, &server}; // same effect
std::this_thread::sleep_for(10ms);
server.stop();
worker.join();
std::clog << std::this_thread::get_id() << " good bye" << std::endl;
}
Possible output:
140435324311360 starting up
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435324311360 good bye
If you believe that a shm_server will only ever be useful if run on its own thread, you can also give it a std::thread as data member and have its constructor (or a dedicated start member function, if you prefer) start and its destructor join the thread.
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
class shm_server
{
std::atomic_bool done_ {};
std::thread worker_ {};
public:
shm_server()
{
this->worker_ = std::thread {&shm_server::run_, this};
}
~shm_server()
{
this->done_.store(true);
if (this->worker_.joinable())
this->worker_.join();
}
private:
void
run_()
{
using namespace std::chrono_literals;
while (!this->done_.load())
{
std::clog << std::this_thread::get_id() << " working..." << std::endl;
std::this_thread::sleep_for(1ms);
}
}
};
int
main()
{
using namespace std::chrono_literals;
std::clog << std::this_thread::get_id() << " starting up" << std::endl;
{
shm_server server {};
std::this_thread::sleep_for(10ms);
}
std::clog << std::this_thread::get_id() << " good bye" << std::endl;
}