Search code examples
c++multithreadingstdthread

Spawn thread and do something else while it's running for as long as it's active


I have a simple program below where some long running process someFn works, sets a state, works sets a state, works and sets a state.

While someFn is running, I want the main thread to query the state it's setting for the lifetime of someFn.

Obviously this code is incorrect because T is joinable until it actually joins and this program does not halt.

How do I correctly get the main thread to loop for the lifetime of T and stop looping as soon as T has terminated?

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

int STATE = 0;
static std::mutex mtx;

void setState(int newState) {
    std::lock_guard<std::mutex> lg(mtx);
    STATE = newState;
}

int getState() {
    std::lock_guard<std::mutex> lg(mtx);
    return STATE;
}


void someFn() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    setState(0);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    setState(1);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    setState(2);
}

int main()
{

    std::thread T(someFn);

    while (T.joinable()) {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        std::cout << getState() << std::endl;
    }

    T.join();

    return 0;

}

Thanks!


Solution

  • Just with std::thread you can't.

    But you can easily craft your own signal. For example:

    #include <atomic>
    #include <chrono>
    #include <iostream>
    #include <mutex>
    #include <thread>
    
    int STATE = 0;
    static std::mutex mtx;
    
    void setState(int newState) {
        std::lock_guard<std::mutex> lg(mtx);
        STATE = newState;
    }
    
    int getState() {
        std::lock_guard<std::mutex> lg(mtx);
        return STATE;
    }
    
    void someFn(std::atomic<bool>& isDone) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        setState(0);
        std::this_thread::sleep_for(std::chrono::seconds(1));
        setState(1);
        std::this_thread::sleep_for(std::chrono::seconds(1));
        setState(2);
        isDone.store(true);
    }
    
    int main() {
        std::atomic<bool> isDone{false};
        std::thread T(someFn, std::ref(isDone));
    
        while(!isDone.load()) {
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
            std::cout << getState() << std::endl;
        }
    
        T.join();
    
        return 0;
    }
    

    You don't need a mutex or other synchronization for std::atomic because it is already thread safe.