1

I would like to use std::this_thread::sleep_for and std::this_thread::sleep_until with std::stop_token where the functions return if stop is requested on std::stop_token (ex. jthread destruction is called). How can I achieve this?

std::jthread thread {[](std::stop_token stoken){
    while(!stoken.stop_requested()) {
        std::cout << "Still working..\n";
        std::this_thread::sleep_for(5s); // use together with stoken
    }
}};
asmbaty
  • 436
  • 2
  • 11
  • 2
    [`std::condition_variable/wait_until`](https://en.cppreference.com/w/cpp/thread/condition_variable/wait_until) might help. – Jarod42 Jun 23 '21 at 07:39
  • 2
    Does this answer your question? [What are common uses of condition variables in C++?](https://stackoverflow.com/questions/2476235/what-are-common-uses-of-condition-variables-in-c) – prehistoricpenguin Jun 23 '21 at 07:45
  • Your code snippet is somewhat similar to the implementation of `std::condition_varialbe::wait` – prehistoricpenguin Jun 23 '21 at 07:46

2 Answers2

6

Use a std::condition_variable, this covers the 'stop when signalled' part. Then you use wait_for or wait_until respectively.

Examples on how to use a condition variable can be found at the links.

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • I am not sure if condition_variable is what I want – asmbaty Jun 23 '21 at 07:45
  • 1
    @asmbaty To cancel the sleeping of a thread, there are not so many (C++ standard conform) ways I can imagine. To tell it from beginning, to wait for a time _or_ a certain condition is a clean way to do so. Hence, I wonder why you have doubts about condition_variable... – Scheff's Cat Jun 23 '21 at 07:54
  • 2
    @asmbaty I'm pretty sure this is what you want. :-) – super Jun 23 '21 at 07:54
  • @asmbaty But that's what STL has forseen for exactly such use cases as you describe. If you don't like that, you likely will have to write a solution entirely on your own – most likely relying on OS-specific functionality to avoid busy-waits (please do so!). – Aconcagua Jun 23 '21 at 07:55
  • std::condition_variable_any::wait_for has an overload since C++20 that receives std::stop_token as an argument. – asmbaty Jun 23 '21 at 11:58
3

Here is my implementation using std::condition_variable as everyone tells that.

template<typename _Rep, typename _Period>
void sleep_for(const std::chrono::duration<_Rep, _Period>& dur, const std::stop_token& stoken)
{
    std::condition_variable_any cv;
    std::mutex mutex_;
    std::unique_lock<std::mutex> ul_ {mutex_};
    std::stop_callback stop_wait {stoken, [&cv](){ cv.notify_one(); }};
    cv.wait_for(ul_, dur, [&stoken](){ return stoken.stop_requested(); });
}
Ben
  • 9,184
  • 1
  • 43
  • 56
asmbaty
  • 436
  • 2
  • 11
  • 1
    This will cause issue mention [here](https://stackoverflow.com/questions/66309276/why-does-c20-stdcondition-variable-not-support-stdstop-token), so you need to use `std::condition_variable_any`. Anyway this give me direction to my problem thanks. – user3724853 Sep 08 '21 at 08:21
  • 1
    So this should be stable when I change std::conditional_variable to std::condition_variable_any? – kurta999 Jun 13 '22 at 09:36