I'm a Java engineer but I need to migrate my Java code to C++.
In C++:
void foo(){
thread t(&loading_function);
t.detach();
}
void loading_function(){
while(true){
//..some loading operations
}
}
//I want to call after loading_function NOT in main thread like t.join();
void loading_after(){
//..loading after handling
}
I want to handling after thread t was end of its process.
Like this Java code:
public class Test implements Runnable{
public void foo(){
Thread loading_thread = new Thread(this);
loading_thread.start();
}
public void run(){
while(true){
//..some loading operations
}
loading_after();
}
public void loading_after(){
//..loading after handling
}
}
How can I do that?
Based on the description on how std::thread::detach() works, I don't think you can detect when it ends, unless you make your loading_function() signal to the outside world that is has ended. There seems to be no built in mechanism for a detached std::thread to signal it has ended. I might be wrong, I have little experience with std::thread.
Alternative would be to make a function that does both loading_function() and loading_after() and pass that function to the std::thread object.
void loading_function()
{
while(true)
{
//..some loading operations
}
}
//I want to call after loading_function NOT in main thread like t.join();
void loading_after()
{
//..loading after handling
}
void load()
{
loading_function();
loading_after();
}
void foo()
{
thread t(&load);
t.detach();
}
Related
Considering the following code, where I declare a simple class for executing asynchronous/threaded operations:
#include <chrono>
#include <thread>
#include <mutex>
#include <future>
#include <iostream>
using namespace std::chrono_literals;
class basic_executor {
public:
basic_executor() {
_mx.lock();
printf("Ctor #%p\n", this);
_mx.unlock();
}
virtual ~basic_executor() {
_mx.lock();
printf("Dtor #%p\n", this);
_mx.unlock();
if (_thread.joinable()) {
_thread.join();
_mx.lock();
printf("Joined thread #%p\n", this);
_mx.unlock();
}
}
// sync call
void run() {
start();
execute();
stop();
}
// async call
void launch(bool detach = false) {
// create packaged task
std::packaged_task< void() > task([this] {
start();
execute();
stop();
});
// assign future object to function return
_done = task.get_future();
// launch function on a separate thread
_thread = std::thread(std::move(task));
// detach them from main thread in order to avoid waiting for them
if (detach == true) {
_thread.detach();
}
}
// blocking wait for async (detached/joinable)
void wait() const {
_done.wait();
}
protected:
virtual void start() { /* for derived types to implement */ }
virtual void stop() { /* for derived types to implement */ }
virtual void execute() { /* for derived types to implement */ }
std::mutex _mx;
std::thread _thread;
std::future< void > _done;
};
And using the following application example where I derive from it to create two logger objects that make dummy prints for a certain span of time:
class logger : public basic_executor {
public:
logger() { /* ... */}
~logger() {
_mx.lock();
std::cout << "logger destructor " << std::endl;
_mx.unlock();
}
void execute() override {
std::this_thread::sleep_for(1s);
for (int i = 0; i < 10; ++i) {
_mx.lock();
printf("L1: I am printing something\n");
_mx.unlock();
std::this_thread::sleep_for(1s);
}
}
void stop() override {
_mx.lock();
printf("L1: I am done!\n");
_mx.unlock();
}
};
class logger2 : public basic_executor {
public:
logger2() { /* ... */}
~logger2() {
_mx.lock();
printf("logger2 destructor\n");
_mx.unlock();
}
void execute() override {
for (int i = 0; i < 10; ++i) {
_mx.lock();
printf("L2: I am ALSO printing something\n");
_mx.unlock();
std::this_thread::sleep_for(2s);
}
}
void stop() override {
_mx.lock();
printf("L2: I am done!\n");
_mx.unlock();
}
};
int main(int argc, char const *argv[]) {
/* code */
// printf("log:\n");
logger log1;
// printf("log1:\n");
logger2 log2;
printf("----------------------------------!\n");
log2.launch();
log1.launch();
// log1.wait();
// log2.wait();
printf("----------------------------------!\n");
return 0;
}
I am getting an unexpected behavior from the program:
Ctor #0x7fff8b18c990
Ctor #0x7fff8b18c9e0
----------------------------------!
----------------------------------!
logger2 destructor
Dtor #0x7fff8b18c9e0
Joined thread #0x7fff8b18c9e0
logger destructor
Dtor #0x7fff8b18c990
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
L1: I am printing something
Joined thread #0x7fff8b18c990
in that occasionally, the 'log2' object never starts its execution before being destroyed, or the 'join()' call on its destructor hangs indefinitely. Is there any obvious reason why this happens, what exactly am I missing here?
The bug can occur with either logging class. However, with undefined behavior you have no guarantees whatsoever, and no expectation of any kind of consistent results. You've only, so far, observed the same bug with one of two logging classes. Although I can explain why is that, in practical terms, it is immaterial. The bug can happen with either of the objects. Let's begin here:
_thread = std::thread(std::move(task));
You are not going to get any guarantees whatsoever that the new execution thread will immediately start executing any of the following before this code proceeds and returns from launch():
std::packaged_task< void() > task([this] {
start();
execute();
stop();
});
Most of the time, practically, this is going to start running pretty quickly, in the new execution thread. But you cannot rely on that. All that C++ guarantees you is that at some point after std::thread finishes constructing a new execution thread will start running. It may be immediate. Or, it may be a few hundred milliseconds later because your operating system had something more important on its plate.
You are expecting that the new execution thread will always start executing "immediately", simultaneous with std::thread getting constructed. That is not true. After all, you might be running with a single CPU core, and after constructing the std::thread object you're continuing to execute what follows in the same execution thread, and only a while later a context switch occurs, to the new execution thread.
Meanwhile:
launch() returns.
The parent execution thread reaches the end of main().
All of the objects in the automatic scope are going to get destroyed, one by one.
In C++, when an object consists of a superclass and a subclass, the subclass gets destroyed first, followed by the superclass. This is how C++ works.
So, the logger/logger2 subclass's destructor gets immediately invoked and it destroys the its object (just the logger/logger2 subclass).
Now the superclass's destructor gets invoked, to destroy the superclass. ~basic_executor starts doing its thing, patiently waiting.
And now, finally, that new execution thread, remember that one? Guess what: it finally starts running, and valiantly tries to execute start(), execute(), and stop(). Or maybe it managed to get through start(), first, but hasn't reached execute() yet. But since the actual logger subclass is already destroyed now, guess what happens? Nothing. It's gone. The subclass is no more. It ceased to be. It joined the choir invisible. It is pining for the fjords. It's an ex-subclass. There is no logger::execute or logger2::execute() any more.
I have a program that I need to run a thread in. The problem is whenever I try to kill this thread from either inside the thread or outside the thread I get a "error 6 - invalid handle" error
class myclass
{
public:
static myclass* inst()
{
if (oInst == nullptr) oInst = new myclass;
return oInst;
};
void main();
void start();
void ex_stop()
{
//HANDLE Stopper = Killer.native_handle();
//TerminateThread(Stopper, 0);
}
}
private:
std::thread Killer;
}
void myclass::start()
{
Killer = std::thread(&myclass::ex_main, this);
Killer.detach();
}
void myclass::main()
{
...
if (0 == TerminateThread(Killer.native_handle(), 0))
{
char error[200];
sprintf(error, "error %i\n", GetLastError());
printf(error);
}
This is how I start the class/thread
myclass::inst()->start();
I've also tried making std::thread Killer an extern and declaring it in my .cpp and .h files, this way I can access it from outside the class, but I still get the same "error 6, invalid thread handle" error.
Can someone please tell me what's wrong with this code? Thanks
The usual way of having a worker thread set up is to put it into a loop, and on each loop check to see if a boolean atomic has been changed ... something that would look like (but this probably doesn't compile straight off; the threadMain will probably need binding)
class myThreadJob {
public:
myThreadJob():
doRun(true),
thread(threadMain)
{}
void threadMain() {
while (doRun) {...}
}
void stop() {
doRun = false;
thread.join();
}
private:
std::atomic<bool> doRun;
std::thread thread;
}
You've not said if your thread is a will do many tasks in a queue, or if it's a one off job that it's doing, but in any case if it's expected to be a long lived thread, it should check periodically that it can still run.
Because you've called detach() on your thread, your thread is no longer associated with your process. You can think of detach() as a declaration that the thread does not need anything local to the creating thread.
You are not allowed to join it; and you're expecting it to run to termination.
Firstly I'd like to point out that I've looked this up but can't find the answer I'm looking for/have got confused with overly detailed answers.
I have a program which uses two threads. A Boolean values need to be set and read in Thread A but only read in Thread B.
Thread A:
Module::Module(){
}
void Module::foo(){
mutex.lock();
bool request = true;
mutex.unlock();
}
void Module::bar(){
mutex.lock();
if (request){
mutex.unlock();
// do stuff
}else{
mutex.unlock();
}
}
Thread B:
Provider::Provider(){
module = new Module; // pointer to class request 'lives in'
}
void Provider::foo(){
mutex.lock();
if (module->request){
mutex.unlock();
// do stuff
}
}else{
mutex.unlock();
}
}
My question might seem rather trivial, but it's bugged me. Thread A cannot read and write at the same time, thus i'd argue recursive mutex is not required for A. However, there is a small possibility foo() and bar() could get called simultaneous from Thread B (Signals and slots). Does this mean I need recursive mutex?
Also; is there any reason not to use a Qt::BlockingQueudConnection? A colleague argued that this is dangerous as it sends calling threads to sleep until the signal has executed the slot- but is this not sort of the same as mutex?
Furthermore; seen a post regarding structuring mutex (pthread mutex locking variables used in statements). In here it mentions making local copies on values. If i was to employ something similar for Thread A e.g.
mutex.lock();
requestCopy = request;
mutex.lock();
...
if(requestCopy){
// do stuff
}
Will this also block access of request whereever requestCopy is getting used? I was looking to use this style in my code for simplicity but this would not work if you read AND write in a thread?
Any help would be great.
From what you have shown, it looks like (rewritten)
Some module (Thread A):
class Module {
private:
bool request = false;
QMutex m;
public:
void set_request(bool b) {
QMutexLocker lock(&m);
request = b;
}
bool get_request() {
QMutexLocker lock(&m);
return request;
}
void bar() {
if (get_request()) {
// do stuff
}
}
};
Thread B:
class Provider {
public:
Provider() {
module = new Module();
}
void foo() {
if (module->get_request()){
// do stuff
}
}
private:
Module *module;
};
If this is really the case (and everything is fine this way), there is no need for a recursive mutex.
I quickly wrote some kind of wrapper to ensure some functionality in a system is always executed in a defined thread context. To make the code as small as possible, I simple use a pointer assignment to check if the thread has started.
void waitForStart() {
while (_handler == nullptr) {
msleep(100); // Sleep for 100ms;
}
msleep(100); // Sleep for 100ms to make sure the pointer is assigned
}
In my opinion, this should work in any case. Even if the assignment to _handler is for unknown reason split up into two operations on a CPU.
Is my assumtion correct? Or did I miss a case where this could go wrong?
For reference a more complete example how the system looks like. There are the System, the Thread and the Handler classes:
class Handler {
public:
void doSomeWork() {
// things are executed here.
}
};
class Thread : public ThreadFromAFramework {
public:
Thread() : _handler(nullptr) {
}
void waitForStart() {
while (_handler == nullptr) {
msleep(100); // Sleep for 100ms;
}
msleep(100); // Sleep for 100ms to make sure the pointer is assigned
}
Handler* handler() const {
return _handler;
}
protected:
virtual void run() { // This method is executed as a new thread
_handler = new Handler();
exec(); // This will go into a event loop
delete _handler;
_handler = nullptr;
}
private:
Handler *_handler;
}
class System {
public:
System() {
_thread = new Thread();
_thread->start(); // Start the thread, this will call run() in the new thread
_thread->waitForStart(); // Make sure we can access the handler.
}
void doSomeWork() {
Handler *handler = _thread->handler();
// "Magically" call doSomeWork() in the context of the thread.
}
private:
Thread *_thread;
}
You missed a case where this can go wrong. The thread might exit 5 msec after it sets the pointer. Accessing any changing variable from two threads is never reliable without synchronization.
After using threads for a while, I got into a situation where I needed a thread to run forever until a a function (or any sort of event) was called. To do this I created a bool value to control a while loop inside the function that was executed by the thread, but I quickly noticed that external variables are not updated after a thread starts running, causing the thread to never stop when it was asked to.
Heres some simple code to represent the issue:
#include <cstdio>
#include <thread>
#include <chrono>
class A {
public:
A();
void startThread();
void endThread();
private:
void threadCall();
bool active;
};
int main() {
A threadThing;
threadThing.startThread();
printf("[M] Thread Created\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
threadThing.endThread();
printf("[M] Thread Killed\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
A::A() {
active = false;
}
void A::startThread() {
active = true;
std::thread AThread(&A::threadCall, *this);
AThread.detach();
}
void A::endThread() {
active = false;
}
void A::threadCall() {
printf("[T] Thread Started\n");
while (active) {
std::this_thread::sleep_for(std::chrono::seconds(2));
}
printf("[T] Thread Ended\n");
}
The expected result of this would be that the main function starts the thread, the thread says it started, then 4 seconds later the thread is killed and the thread says it ended, when in reality the thread never says it ends. Is there a way to let the thread access the 'active' variable, or is my approach to this problem incorrect altogether? (Side note, I did try to figure this out on my own but only got stuff like local thread storage which seems like its only for storage inside of threads, not access to the outside but I could be wrong)
The problem is with the constructor of std::thread, it copies/moves by default.
std::thread AThread(&A::threadCall, *this);
this copies the object into the new thread, so checking the active variable in the new object has no effect.
you can remove the *
std::thread AThread(&A::threadCall, this);
you pass the object pointer into the new thread, it will call like the method like this(*this).threadCall().
Edit: as the comments say, this is not guarantee to be thread safe, you need to use std::atomic<bool> to be safe.
What you need to do is pass an A class pointer as an argument to your function that is your thread.
void A::startThread()
{
active = true;
std::thread AThread(threadCall, this);
AThread.detach();
}
void A::threadCall(A *aClass)
{
printf("[T] Thread Started\n");
while (aClass->active)
{
std::this_thread::sleep_for(std::chrono::seconds(2));
}
printf("[T] Thread Ended\n");
}