How to suspend (and resume) 'std::thread' from another thread?
Asked Answered
E

3

22

I am new to std::thread. I need to put a std::thread to sleep from another thread, is that possible? In examples, all I see is code like:

std::this_thread::sleep_for(std::chrono::seconds(1));

But what I want to do is something like:

std::thread t([]{...});
t.sleep(std::chrono::seconds(1));

or sleep(t, std::chrono::seconds(1));

Any ideas?

Emergent answered 12/10, 2012 at 12:55 Comment(2)
Honestly, the best solution is to solve whatever problem you're having some sensible way. There is really no reason you should ever want to put a thread to sleep from another thread. If the thread is doing work you want done now, why put it to sleep? If the thread isn't doing work you want done now, then its code is broken and you should fix it.Chimera
Possibly what you really want to use is std::condition_variable and its methods like wait(...) or wait_for(...)Endoderm
L
29

Because sleep_for is synchronous, it only really makes sense in the current thread. What you want is a way to suspend / resume other threads. The standard does not provide a way to do this (afaik), but you can use platform-dependent methods using native_handle.

For example on Windows, SuspendThread and ResumeThread.

But more important is that there is almost never a need to do this. Usually when you encounter basic things you need that the standard doesn't provide, it's a red flag that you're heading down a dangerous design path. Consider accomplishing your bigger goal in a different way.

Lard answered 12/10, 2012 at 13:1 Comment(1)
The "red flag" is valid and very good advice! But also not absolute, so think it through carefully - the language is constantly changing as a result of programmers continuously discovering weaknesses, drawbacks, oversights, useful extensions, and failures.Maw
C
15

No. The standard doesn't give you such a facility, and it shouldn't. What does sleep do? It pauses the execution of a given thread for a at least the given amount of time. Can other threads possibly know without synchronizing that the given thread can be put to sleep in order to achieve a better performance?

No. You would have to provide an synchronized interface, which would counter the performance gain from threads. The only thread which has the needed information whether it's ok to sleep is the thread itself. Therefore std::thread has no member sleep, while std::this_thread has one.

Crites answered 12/10, 2012 at 12:59 Comment(0)
D
0

To control a custom thread execution, something like that works:

#include <atomic>
#include <thread>
#include <iostream>
#include <condition_variable>


class WorkerControl
{
public:

    void Suspend()
    { 
        sleep_ = true;
    };

    void Resume()
    {
        sleep_ = false;
        cv_.notify_one();
    };

    void Exit()
    {
        exit_ = true;
    };

    std::atomic_bool sleep_{ false };
    std::condition_variable cv_{};
    std::atomic_bool exit_{ false };
    std::mutex mutex_{};
};


void Worker(WorkerControl& control)
{
    std::unique_lock lk(control.mutex_);

    while (!control.exit_.load()) {
        if (!control.sleep_.load()) {
            std::cout << ".";
            std::this_thread::sleep_for(std::chrono::milliseconds(500)); // (Some work to do) 
        }
        else {
            std::cout << "\n" << "enters sleep" << "\n";
            control.cv_.wait(lk, [&control]() { return control.sleep_.load() == false; });
            std::cout << "wakes up" << "\n";
        }
    }

    std::cout << "\n" << "exits" << "\n";
}


int main()
{
    WorkerControl control{};
    std::thread tr(Worker, std::ref(control));

    // For example:

    std::this_thread::sleep_for(std::chrono::seconds(5)); // (Do something 5 seconds)

    control.Suspend();

    std::this_thread::sleep_for(std::chrono::seconds(3)); // (Do something 3 seconds)

    control.Resume();

    std::this_thread::sleep_for(std::chrono::seconds(10)); // (Do something 10 seconds)

    control.Suspend();

    std::this_thread::sleep_for(std::chrono::seconds(3)); // (Do something 3 seconds)

    control.Resume();

    std::this_thread::sleep_for(std::chrono::seconds(5)); // (Do something 5 seconds)

    control.Exit();

    tr.join();
}

Output:

..........
suspended
resumed
....................
suspended
resumed
..........
exited

Demo

Ddene answered 28/10, 2023 at 15:0 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.