1

I'm going to have a function capable of generating auto-destructive threads. The problem is that I'm not allowed to reuse the function until the created thread has finished. On the other hand, I want the spawned thread to continue running outside the scope of the function and be destroyed whenever the thread is done.

My code is as follows.

#include <iostream>
#include <thread>
#include <chrono>

struct ThreadGaurd
{
public:

    ThreadGaurd(void (*Func) (int) , int number);

    ~ThreadGaurd();
private:
public:

    std::thread m_Thread;
private:
};


void CreateThread()
{
    static int Counter = 0;
    ThreadGaurd m_Thread([](int counter)
    {
        std::chrono::duration<double, std::milli> m_Duration(500);

        while (true) {
            std::this_thread::sleep_for(m_Duration);

            std::cout << "My " << counter << "'th Thread is Running";
        }
    }, Counter);

    return;
} 

int main(int argc, char *argv[])
{
    CreateThread();
    CreateThread();
    return 0;
}

ThreadGaurd::ThreadGaurd(void (*Func)(int), int number) : m_Thread(Func,number)
{
}

ThreadGaurd::~ThreadGaurd()
{
    if (m_Thread.joinable())
        m_Thread.join(); 
}

1 Answers1

4

You want to call std::thread::detach on the thread. After detach returns, it is safe to destroy the std::thread object as the thread is no longer associated with the object and will continue running independently.

The following code demonstrates using detach.

Sample Code

#include <iostream>
#include <thread>
#include <chrono>

using std::cout, std::endl;
using namespace std::chrono_literals;

template<class F>
void create_detached_thread(F&& func) {
    std::thread th{std::forward<F>(func)};
    th.detach();
}

int main(int argc, const char *argv[]) {
    cout << "Main started" << endl;

    create_detached_thread([]() {
        cout << "First thread starting" << endl;
        std::this_thread::sleep_for(400ms);
        cout << "First thread done" << endl;

    });

    create_detached_thread([]() {
        cout << "Second thread starting" << endl;
        std::this_thread::sleep_for(200ms);
        cout << "Second thread done" << endl;
    });

    cout << "Main sleeping" << endl;
    std::this_thread::sleep_for(1s);
    cout << "Main done" << endl;
    return 0;
}

Output

Main started
Main sleeping
Second thread starting
First thread starting
Second thread done
First thread done
Main done

As explained in this answer, you have to call either join or detach on a thread before the std::thread object is destroyed, otherwise std::terminate is called.

If you need to use detach, you will probably want to provide a synchronization mechanism so that the main thread will not end unless all of the detach'ed threads have finished.

Update

The following code is the same as above except it uses a std::atomic<int> to wait for the two detached threads to finish before allowing main to finish.

#include <atomic>
#include <iostream>
#include <thread>
#include <chrono>

using std::cout, std::endl;
using namespace std::chrono_literals;

template<class F>
void create_detached_thread(F&& func) {
    std::thread th{std::forward<F>(func)};
    th.detach();
}

int main(int argc, const char *argv[]) {
    cout << "Main started" << endl;

    std::atomic<int> ndone{};

    create_detached_thread([&]() {
        cout << "First thread starting" << endl;
        std::this_thread::sleep_for(400ms);
        cout << "First thread done" << endl;
        ++ndone;
        ndone.notify_one();
    });

    create_detached_thread([&]() {
        cout << "Second thread starting" << endl;
        std::this_thread::sleep_for(200ms);
        cout << "Second thread done" << endl;
        ++ndone;
        ndone.notify_one();
    });

    cout << "Main sleeping" << endl;
    ndone.wait(0);
    ndone.wait(1);
    cout << "Main done" << endl;
    return 0;
}
RandomBits
  • 4,194
  • 1
  • 17
  • 30
  • Instead of waiting to finish, use `std::jthread` with`std::stop_token` for automatic `join` on destruction. – Red.Wave May 26 '23 at 10:42