How to make boost threads self-destruct? (C++) - c++

I have a class with some function like:
void workerFunc(int ClassVariable)
{
boost::posix_time::seconds workTime(classVariableA);
std::cout << "Worker: running" << std::endl;
// Pretend to do something useful...
boost::this_thread::sleep(workTime);
std::cout << ClassVariable << std::endl;
std::cout << "Worker: finished" << std::endl;
}
which I want to be in threads. and some other function that I want to work like
while(1)
{
boost::thread workerThread(workerFunc(ClassVariableB));
}
so it will create thread each time it can. But what I need is for that thread to auto destruct itself when it is finished. How to do such thing?

You do not have to do anything for that. You just have to make sure that the thread really finishes (i.e. no infinite loops or such).

A thread will automatically end when it finishes running the function for which it was created.
join is a strange word, it really means wait_for which means wait for the thread to finish executing.
If you want to retain a thread for re-use, it is normally implemented by making its function loop, each time reaching a "wait" state, where it gets alerted (woken up) when something it is waiting for happens. At some point this will be a termination request, or a request that leads to its termination.

Related

In C++, how to pause and resume a thread from outside?

I want to pause and resume a thread from outside, and at any time (not at certain breakpoints, and thus wait and notify won't work).
For example, we create a thread in foo(), and then it keeps running. (the Thread could be any thread class similar to std::thread)
void A::foo() {
this->th = Thread([]{
// This thread runs a time-consuming job with many steps
// I hope to pause and resume it at any time outside ths thread (e.g. press a button)
});
}
I need to pause and resume the thread outside the thread, maybe by calling methods like this...
void A::bar() {
this->th->pause();
cout << "The thread is paused now" << endl;
}
void A::baz() {
this->th->resume();
cout << "The thread is resumed now" << endl;
}
How can I implement this in C++?
#freakish said it can be done with pthread and signals, but no portable way.
In Windows, I just found SuspendThread(t.native_handle()) and ResumeThread(t.native_handle()) (where t is of type std::thread) are available. These would solve my problem.

Confusion about boost::asio::io_context::run

I am currently working on a project where I use the MQTT protocol for communication.
There is a Session class in a dedicated file which basically just sets up the publish handler, i.e. the callback that is invoked, when this client receives a message (the handler checks if the topic matches "ZEUXX/var", then deserialized the binary content of the frame and subsequently unsubscribes the topic):
session.hpp:
class Session
{
public:
Session()
{
comobj = MQTT_NS::make_sync_client(ioc, "localhost", "1883", MQTT_NS::protocol_version::v5);
using packet_id_t = typename std::remove_reference_t<decltype(*comobj)>::packet_id_t;
// Setup client
comobj->set_client_id(clientId);
comobj->set_clean_session(true);
/* If someone sends commands to this client */
comobj->set_v5_publish_handler( // use v5 handler
[&](MQTT_NS::optional<packet_id_t> /*packet_id*/,
MQTT_NS::publish_options pubopts,
MQTT_NS::buffer topic_name,
MQTT_NS::buffer contents,
MQTT_NS::v5::properties /*props*/) {
std::cout << "[client] publish received. "
<< " dup: " << pubopts.get_dup()
<< " qos: " << pubopts.get_qos()
<< " retain: " << pubopts.get_retain() << std::endl;
std::string_view topic = std::string_view(topic_name.data(), topic_name.size());
std::cout << " -> topic: " << topic << std::endl;
else if (topic.substr(0, 9) == "ZEUXX/var")
{
std::cout << "[client] reading variable name: " << topic.substr(10, topic.size() - 9) << std::endl;
auto result = 99; // dummy variable, normally an std::variant of float, int32_t uint8_t
// obtained by deserialzing the binary content of the frame
std::cout << comobj->unsubscribe(std::string{topic});
}
return true;
});
}
void readvar(const std::string &varname)
{
comobj->publish(serialnumber + "/read", varname, MQTT_NS::qos::at_most_once);
comobj->subscribe(serialnumber + "/var/" + varname, MQTT_NS::qos::at_most_once);
}
void couple()
{
comobj->connect();
ioc.run();
}
void decouple()
{
comobj->disconnect();
std::cout << "[client] disconnected..." << std::endl;
}
private:
std::shared_ptr<
MQTT_NS::callable_overlay<
MQTT_NS::sync_client<MQTT_NS::tcp_endpoint<as::ip::tcp::socket, as::io_context::strand>>>>
comobj;
boost::asio::io_context ioc;
};
The client is based on a boost::asio::io_context object which happens to be the origin of my confusion. In my main file I have the following code.
main.cpp:
#include "session.hpp"
int main()
{
Session session;
session.couple();
session.readvar("speedcpu");
}
Essentially, this creates an instance of the class Session and the couple member invokes the boost::asio::io_context::run member. This runs the io_context object's event processing loop and blocks the main thread, i.e. the third line in the main function will never be reached.
I would like to initiate a connection (session.couple) and subsequently do my publish and subscribe commands (session.readvar). My question is: How do I do that correctly?
Conceptionally what I aim for is best expressed by the following python-code:
client.connect("localhost", 1883)
# client.loop_forever() that's what happens at the moment, the program
# doesn't continue from here
# The process loop get's started, however it does not block the program and
# one can send publish command subsequently.
client.loop_start()
while True:
client.publish("ZEUXX/read", "testread")
time.sleep(20)
Running the io_context object in a separate thread seems not to be working the way I tried it, any suggestions on how to tackle this problem? What I tried is the following:
Adaption in session.hpp
// Adapt the couple function to run io_context in a separate thread
void couple()
{
comobj->connect();
std::thread t(boost::bind(&boost::asio::io_context::run, &ioc));
t.detach();
}
Adpations in main.cpp
int main(int argc, char** argv)
{
Session session;
session.couple();
std::cout << "successfully started io context in separate thread" << std::endl;
session.readvar("speedcpu");
}
The std::cout line is now reached, i.e. the program does not get stuck in the couple member of the class by io_context.run(). However directly after this line I get an error: "The network connection was aborted by the local system".
The interesting thing about this is that when I use t.join() instead of t.detach() then there is no error, however I have the same behavior with t.join() as when I call io_context.run() directly, namely blocking the program.
Given your comment to the existing answer:
io_context.run() never return because it never runs out of work (it is being kept alive from the MQTT server). As a result, the thread gets blocked as soon as I enter the run() method and I cannot send any publish and subscribe frames anymore. That was when I thought it would be clever to run the io_context in a separate thread to not block the main thread. However, when I detach this separate thread, the connection runs into an error, if I use join however, it works fine but the main thread gets blocked again.
I'll assume you know how to get this running successfully in a separate thread. The "problem" you're facing is that since io_context doesn't run out of work, calling thread::join will block as well, since it will wait for the thread to stop executing. The simplest solution is to call io_context::stop before the thread::join. From the official docs:
This function does not block, but instead simply signals the io_context to stop. All invocations of its run() or run_one() member functions should return as soon as possible. Subsequent calls to run(), run_one(), poll() or poll_one() will return immediately until restart() is called.
That is, calling io_context::stop will cause the io_context::run call to return ("as soon as possible") and thus make the related thread joinable.
You will also want to save the reference to the thread somewhere (possibly as an attribute of the Session class) and only call thread::join after you've done the rest of the work (e.g. called the Session::readvar) and not from within the Session::couple.
When io_context runs out of work, it returns from run().
If you don't post any work, run() will always immediately return. Any subsequent run() also immediately returns, even if new work was posted.
To re-use io_context after it completed, use io_context.reset(). In your case, better to
use a work guard (https://www.boost.org/doc/libs/1_73_0/doc/html/boost_asio/reference/executor_work_guard.html), see many of the library examples
don't even "run" the ioc in couple() if you already run it on a background thread
If you need synchronous behaviour, don't run it on a background thread.
Also keep in mind that you need to afford graceful shutdown which is strictly harder with a detached thread - after all, now you can't join() it to know when it exited.

Thread crashing when trying to join

Update
I did as recommended to create a std::vector of threads outside the scope, so I can .join() as soon as the thread has finished it's job, the problem now is that as soon as the thread is joined the program not exactly crashes, because it still runs in the background but the abort window appears. I checked if the thread was joinable and indeed it is when trying to join.
Timer.cpp:
void Timer::Start(int time, void(*lf)()) {
slaveTimer = std::thread(&Timer::RunTimer, this, time, lf);
}
void Timer::RunTimer(int seconds, void(*lf)()) {
auto time = (std::chrono::seconds)seconds;
std::this_thread::sleep_for(time);
lf();
slaveTimer.join(); //Program Crashes
}
Main.cpp
Timer timer1(10, [](){ std::cout << "Hello World" << std::endl; });
Original Post
I was trying to make coroutines with multithreading, the thing is that when I try to make the thread wait for X seconds, i then thread.detach(); but that takes a couple of milliseconds and the screen (because I’m displaying with GL) freezes. One of the possible solutions that I can think of is making the thread detach itself before executing the action, but that doesn’t seem possible, so I was wondering if there is any way to do that or something similar to solve this problem.
You cannot call join from the function which is the body of execution thread. It will give you the error:
Reference
Error Conditions :
resource_deadlock_would_occur if this->get_id() ==
std::this_thread::get_id() (deadlock detected)
you need to add additional method for instance
void Timer::stop() {
slaveTimer.join();
}
and call this method from thread which created timer1 instance
Timer timer1(10, [](){ std::cout << "Hello World" << std::endl; });
timer1.stop();
or join thread in dtor of Timer:
Timer::~Timer() {
slaveTimer.join();
}

When should I use std::thread::detach?

Sometime I have to use std::thread to speed up my application. I also know join() waits until a thread completes. This is easy to understand, but what's the difference between calling detach() and not calling it?
I thought that without detach(), the thread's method will work using a thread independently.
Not detaching:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called without detach");
});
//some code here
}
Calling with detaching:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called with detach");
});
t.detach();
//some code here
}
In the destructor of std::thread, std::terminate is called if:
the thread was not joined (with t.join())
and was not detached either (with t.detach())
Thus, you should always either join or detach a thread before the flows of execution reaches the destructor.
When a program terminates (ie, main returns) the remaining detached threads executing in the background are not waited upon; instead their execution is suspended and their thread-local objects destructed.
Crucially, this means that the stack of those threads is not unwound and thus some destructors are not executed. Depending on the actions those destructors were supposed to undertake, this might be as bad a situation as if the program had crashed or had been killed. Hopefully the OS will release the locks on files, etc... but you could have corrupted shared memory, half-written files, and the like.
So, should you use join or detach ?
Use join
Unless you need to have more flexibility AND are willing to provide a synchronization mechanism to wait for the thread completion on your own, in which case you may use detach
You should call detach if you're not going to wait for the thread to complete with join but the thread instead will just keep running until it's done and then terminate without having the spawner thread waiting for it specifically; e.g.
std::thread(func).detach(); // It's done when it's done
detach basically will release the resources needed to be able to implement join.
It is a fatal error if a thread object ends its life and neither join nor detach has been called; in this case terminate is invoked.
This answer is aimed at answering question in the title, rather than explaining the difference between join and detach. So when should std::thread::detach be used?
In properly maintained C++ code std::thread::detach should not be used at all. Programmer must ensure that all the created threads gracefully exit releasing all the acquired resources and performing other necessary cleanup actions. This implies that giving up ownership of threads by invoking detach is not an option and therefore join should be used in all scenarios.
However some applications rely on old and often not well designed and supported APIs that may contain indefinitely blocking functions. Moving invocations of these functions into a dedicated thread to avoid blocking other stuff is a common practice. There is no way to make such a thread to exit gracefully so use of join will just lead to primary thread blocking. That's a situation when using detach would be a less evil alternative to, say, allocating thread object with dynamic storage duration and then purposely leaking it.
#include <LegacyApi.hpp>
#include <thread>
auto LegacyApiThreadEntry(void)
{
auto result{NastyBlockingFunction()};
// do something...
}
int main()
{
::std::thread legacy_api_thread{&LegacyApiThreadEntry};
// do something...
legacy_api_thread.detach();
return 0;
}
When you detach thread it means that you don't have to join() it before exiting main().
Thread library will actually wait for each such thread below-main, but you should not care about it.
detach() is mainly useful when you have a task that has to be done in background, but you don't care about its execution. This is usually a case for some libraries. They may silently create a background worker thread and detach it so you won't even notice it.
According to cppreference.com:
Separates the thread of execution from the thread object, allowing
execution to continue independently. Any allocated resources will be
freed once the thread exits.
After calling detach *this no longer owns any thread.
For example:
std::thread my_thread([&](){XXXX});
my_thread.detach();
Notice the local variable: my_thread, while the lifetime of my_thread is over, the destructor of std::thread will be called, and std::terminate() will be called within the destructor.
But if you use detach(), you should not use my_thread anymore, even if the lifetime of my_thread is over, nothing will happen to the new thread.
Maybe it is good idea to iterate what was mentioned in one of the answers above: When the main function is finished and main thread is closing, all spawn threads either will be terminated or suspended. So, if you are relying on detach to have a background thread continue running after the main thread is shutdown, you are in for a surprise. To see the effect try the following. If you uncomment the last sleep call, then the output file will be created and written to fine. Otherwise not:
#include <mutex>
#include <thread>
#include <iostream>
#include <fstream>
#include <array>
#include <chrono>
using Ms = std::chrono::milliseconds;
std::once_flag oflag;
std::mutex mx;
std::mutex printMx;
int globalCount{};
std::ofstream *logfile;
void do_one_time_task() {
//printMx.lock();
//std::cout<<"I am in thread with thread id: "<< std::this_thread::get_id() << std::endl;
//printMx.unlock();
std::call_once(oflag, [&]() {
// std::cout << "Called once by thread: " << std::this_thread::get_id() << std::endl;
// std::cout<<"Initialized globalCount to 3\n";
globalCount = 3;
logfile = new std::ofstream("testlog.txt");
//logfile.open("testlog.txt");
});
std::this_thread::sleep_for(Ms(100));
// some more here
for(int i=0; i<10; ++i){
mx.lock();
++globalCount;
*logfile << "thread: "<< std::this_thread::get_id() <<", globalCount = " << globalCount << std::endl;
std::this_thread::sleep_for(Ms(50));
mx.unlock();
std::this_thread::sleep_for(Ms(2));
}
std::this_thread::sleep_for(Ms(2000));
std::call_once(oflag, [&]() {
//std::cout << "Called once by thread: " << std::this_thread::get_id() << std::endl;
//std::cout << "closing logfile:\n";
logfile->close();
});
}
int main()
{
std::array<std::thread, 5> thArray;
for (int i = 0; i < 5; ++i)
thArray[i] = std::thread(do_one_time_task);
for (int i = 0; i < 5; ++i)
thArray[i].detach();
//std::this_thread::sleep_for(Ms(5000));
std::cout << "Main: globalCount = " << globalCount << std::endl;
return 0;
}

Threading In Classes

I am creating an asynchronous class that logs strings into a file. Should I be creating the thread within the class itself? I was thinking something like this as a start function
void Async_Log::start (void)
{
std::thread thread_log(
[&]()
{
std::ofstream fout;
fout.open(fileName);
while(true)
{
if(q.size())
{
std::lock_guard<std::mutex> lock(m);
fout << q.front() << "\t At Time: " << std::clock() << std::endl;
q.pop();
}
}
fout.close();
});
}
Or would it be better to leave the threading up to main. My first concern is if threading is unique (so if I instantiate the class 2 times with two different files will the thread_log be over written or have a conflict).
There is nothing wrong to have a dedicated thread in the class, but I want to note several things:
Inside your thread you implement busy waiting for log messages. This is completely redundant and very expensive! Your thread consumes CPU even when there are no messages in the queue. What you need is blocking queue there, that would block on pop() method. You can find implementation of the blocking queue for C++ here or here.
There is need to provide possibilty to terminate your logging thread. This you can do eigher by having 'terminate' variable that you check in the loop, or by sending special 'poison pill' message to the logger.