threads

Hello there,

I was wondering if anyone may know of a way to control a timed loop without using concurrency. As it stands I am using threads to carry out operations within a loop and when the timer runs out the loop will stop , however it is causing problems with containers in the way of deletion.

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
  timer(unsigned int period_secs, atomic<bool>& keep_running)
	
{
const auto interval = chrono::seconds(period_secs);
int cnt = 5;

while (keep_running)
{
   {
      /*lock_guard<mutex> guard(cout_lock);*/ //<---?
      --cnt;
			
      if (cnt == 0) {
      keep_running = false;
      cout << "end of while loop";
					
		}

		}

		this_thread::sleep_for(interval);
		}

	}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
atomic<bool> keep_running{ true };
	thread(round_timer, this, 1, ref(keep_running)).detach();
	


	while (keep_running != false) {

		dofunc1(); 
		dofunc2();
		dofunc3();

	}
this_thread::sleep_for(std::chrono::milliseconds(500));

->> otherfuncs();  /problems occur here with other operations


Is there a way possibly to use the lock guard mutex in this instance to prevent these problems? Or any other way to run the loop without disrupting user input within the functions inside the loop without using threads.

Thanks
Last edited on
1
2
3
4
5
6
7
8
9
10
11
const unsigned int timeout_period_secs = 5 ;
const auto end_time = std::chrono::steady_clock::now() +
                      std::chrono::milliseconds(timeout_period_secs) ;

// when the timer runs out the loop will stop
while( std::chrono::steady_clock::now() < end_time )
{
    dofunc1();
    dofunc2();
    dofunc3();
}
JLBorges: if any of the dofunc()'s depend on stdio then they'd block the program even after 5 secs are up, is there a way to get around that? Thanks.
ps. the example I was thinking of is something like this:
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
# include <iostream>
# include <string>
# include <thread>
# include <chrono>

void dofunc1()
{
    std::cout << "enter your name \n";
    std::string name;
    getline(std::cin, name);
    std::cout << name;
}

int main()
{
    const unsigned int timeout_period_secs = 5 ;
    const auto end_time = std::chrono::steady_clock::now() +
                      std::chrono::milliseconds(timeout_period_secs) ;

// when the timer runs out the loop will stop
while( std::chrono::steady_clock::now() < end_time )
{
    dofunc1();
   // dofunc2();
    //dofunc3();
}
}


OP: incidentally I found this re time-controlled user-inputs that eschews getline(), etc in favor of kbhit, getch etc (admittedly OS specific):
https://cboard.cprogramming.com/cplusplus-programming/173004-time-controlled-user-input.html?highlight=
Last edited on
> if any of the dofunc()'s depend on stdio then they'd block the program even after 5 secs are up,
> is there a way to get around that?

There is no standard way to do this (fully cancel an i/o operation after a timeout period has expired).

The sentry is constructed and checked before the actual input operation on the stream is attempted. Once the sentry reports that the preparation of the stream object for input was successful, the input request is forwarded to the stream buffer.

So, something like this (which attempts to kill pending input on the stream buffer by setting the stream to a failed state) won't work. (It would abort further attempted input; but it will do so only after the on-going blocking call on the stream buffer has returned.)

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
47
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <future>

void dofunc1()
{
    std::cout << "enter your name \n" << std::flush ;

    std::string name;
    if( std::getline( std::cin, name ) ) std::cout << name << '\n' ;
    else std::cerr << "input failed\n" ;
}

int main()
{
    const auto timeout_period_secs = std::chrono::seconds(3) ;
    const auto end_time = std::chrono::steady_clock::now() + timeout_period_secs ;

    bool killed = false ;
    const auto kill_stdin_on_timeout = [&] ()
    {
        std::this_thread::sleep_for(timeout_period_secs) ;
        if( std::cin )
        {
            std::cout << "trying to put std::cin into a failed state\n" << std::flush ;

            // assumes that std::ios_base::sync_with_stdio(false) has not been called
            std::cin.clear(std::ios::failbit) ;

            std::cout << "done putting std::cin into a failed state\n" << std::flush ;
            killed = true ;
        }
    };

    auto future = std::async( std::launch::async, kill_stdin_on_timeout ) ;

    // when the timer runs out the loop will stop
    while( std::chrono::steady_clock::now() < end_time )
    {
        dofunc1();
    }

    future.get() ;
    if(killed) std::cin.clear() ; // put cin back to a good state
}
Topic archived. No new replies allowed.