Asynchronous timer and loops

Hello, i'm just trying to create a sort of asynchronous timer.

I've found a code on a website:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <chrono>
#include <iostream>
#include <future>

void timer() {
    std::cout << "Start\n";
    for(int i=0;i<10;++i)
    {
        std::cout << (10-i) << '\n';
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    std::cout << "DONE\n";
}
int main ()
{
    auto future = std::async(timer);
    std::cout << "test\n";
}

If the operation performed in timer() takes significant time you can get better accuracy like this:

void timer() {
    std::cout << "Start\n";
    auto start = std::chrono::high_resolution_clock::now();
    for(int i=0;i<10;++i)
    {
        std::cout << (10-i) << '\n';
        std::this_thread::sleep_until(start + (i+1)*std::chrono::seconds(1));
    }
    std::cout << "DONE\n";
}


Now, using the code in the main() function, it doesn't work for me.
I have to say that after calling the timer code, i enter in a loop that wait for input (cin).

Maybe the cin is blocking everything else?

Thank you.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <chrono>
#include <type_traits>
#include <future>
#include <thread>

struct stop_watch
{
    using wall_clock = typename std::conditional< std::chrono::high_resolution_clock::is_steady,
                                                  std::chrono::high_resolution_clock,
                                                  std::chrono::steady_clock >::type ;

    const wall_clock::time_point start = wall_clock::now() ;
    wall_clock::time_point end = start ;

    stop_watch() = default ;

    void stop() { end = wall_clock::now() ; }

    unsigned long long elapsed() const
    { return std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() ; }

    template < typename CALLABLE, typename... ARGS >
    static unsigned long long time_it( CALLABLE&& fn, ARGS&&... args )
    {
        stop_watch sw ;
        std::forward<CALLABLE>(fn)( std::forward<ARGS>(args)... ) ;
        sw.stop() ;
        return sw.elapsed() ;
    }
};

void foo( unsigned int msecs )
{
    std::this_thread::sleep_for( std::chrono::milliseconds(msecs) ) ;
}

int main()
{
    auto future = std::async( std::launch::async, [] { return stop_watch::time_it( foo, 2345 ) ; } ) ;

    while( future.wait_for( std::chrono::milliseconds(300) ) != std::future_status::ready )
        std::cout << "waiting... " << std::flush ;

    std::cout << " for " << future.get() << " milliseconds\n" ;
}

http://coliru.stacked-crooked.com/a/9a3a088fa3789e81
http://rextester.com/LNY97688
Thank you for the informations.

Sorry for the late replay.

I would like to do something Asynchronously while i get the input from the keyboard in the console windows
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <chrono>
#include <string>
#include <future>

std::string get_input_from_keyboard( std::string prompt )
{
    std::cout << prompt << '\n' ;
    std::string str ;
    std::getline( std::cin, str ) ;
    return str ;
}

int main()
{
    // http://en.cppreference.com/w/cpp/thread/async
    auto future = std::async( std::launch::async, get_input_from_keyboard, "input? " ) ;

    // http://en.cppreference.com/w/cpp/thread/future/wait_for
    while( future.wait_for( std::chrono::milliseconds(500) ) != std::future_status::ready )
        std::cout << "do something while waiting for input...\n" << std::flush ;

    const std::string input = future.get() ; // http://en.cppreference.com/w/cpp/thread/future/get
    std::cout << "\ninput is '" << input << "'\n" ;
}
Thank you all for the informations.

Assuming i want to repeat endlessly the timer function, it's a bad pratics to do as follow:
1
2
3
4
5
6
7
8
9
10
11
void timer() {
    std::cout << "Start\n";
    auto start = std::chrono::high_resolution_clock::now();
    for(int i=0;i<10;++i)
    {
        std::cout << (10-i) << '\n';
        std::this_thread::sleep_until(start + (i+1)*std::chrono::seconds(1));
    }
    std::cout << "DONE\n";
    timer();
}


I add to the function a call to itself.
Last edited on
Running a recursive function endlessly is not a good idea; it may waste stack space and if run long enough, may eventually run out of stack space.

An iterative version would be fine:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <chrono>
#include <thread>
#include <atomic>
#include <mutex>
#include <string>

std::mutex cout_lock ;

void repeat_print_message( unsigned int period_msecs, std::atomic<bool>& keep_running, std::string msg )
{
    const auto interval = std::chrono::milliseconds(period_msecs) ;
    int cnt = 0 ;

    while( keep_running )
    {
        {
            std::lock_guard<std::mutex> guard(cout_lock) ;
            std::cout << ++cnt << ". " << msg << '\n' << std::flush ;
        }

        std::this_thread::sleep_for(interval) ;
    }
}

int main()
{
    const std::string baba = "Baa, baa, black sheep," ;
    const std::string haveu = "Have you any wool?" ;
    std::atomic<bool> keep_running {true} ;

    std::thread( repeat_print_message, 200, std::ref(keep_running), baba ).detach() ; // every 200 ms
    std::thread( repeat_print_message, 500, std::ref(keep_running), haveu ).detach() ; // every 500 ms

    std::this_thread::sleep_for( std::chrono::seconds(3) ) ;
    keep_running = false ; // ask he threads to quit
    std::this_thread::sleep_for( std::chrono::milliseconds(500) ) ; // give them a bit of time to exit cleanly
}

http://coliru.stacked-crooked.com/a/2bf338ea28d0f1e4
http://rextester.com/NMZ31626
Thank you.

Really interesting.

you put this last 3 lines:

1
2
3
std::this_thread::sleep_for( std::chrono::seconds(3) ) ;
    keep_running = false ; // ask he threads to quit
    std::this_thread::sleep_for( std::chrono::milliseconds(500) ) ; // give them a bit of time to exit cleanly 


Could you give me further informations?

To which thread "this_thread" is referring to, to the main() thread?
setting keep_running=false cause the detach?
Last edited on
> To which thread "this_thread" is referring to

std::this_thread is a namespace.
The functions in this namespace are used to manage 'the current thread' - ie. the thread that calls these functions.

When we use std::this_thread::sleep_for( std::chrono::seconds(3) ) ; in main(),
it pauses the execution of main() for at least three seconds.


> setting keep_running=false cause the detach?

No. In the snippet, the thread is detached immediately after creation.
std::thread( repeat_print_message, 200, std::ref(keep_running), baba ).detach() ;

keep_running is an atomic boolean flag, passed to the function by reference.
void repeat_print_message( unsigned int period_msecs, std::atomic<bool>& keep_running, std::string msg );

std::thread( repeat_print_message, 200, std::ref(keep_running), baba ).detach() ;

In repeat_print_message(), the loop while(keep_running) ends, and the function returns when this flag is false.

Just before exiting from main(), we set the flag to false, and then wait for a little time to let the detached threads terminate gracefully before we end the program by returning from main().
Topic archived. No new replies allowed.