Interrupting loop using keyboard input

Hello,
I was wondering if there is a simple solution to my problem - interrupting infinite (or very long) loop using keyboard input.

Since I expect accessing hardware is mainly done through OS I am asking in this forum(windows in my case).

Pseudo-code to demonstrate what do I want to achieve:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

volatile bool isInterrupted = false; //Interrupt flag

void keyIsPressed()   //This function is run immidiatelly when the key (for example ESC) is pressed
{
   isInterrupted = true;
}  //Now the precedure returns back to the loop (where it was interrupted)

int main()
{
   //Pre-loop action...

   while(isInterrupted == false){
      //Do all the calculations
   }
   
   //Post-loop action...
}


Now, because one loop cycle can take for example 5 minutes I can't use solution recommended in many discussion - based on cin.getline(). From what I undestood it requires the user to hold down the ESC key exactly in the moment when the procedure is asking for this getline().
1
2
3
4
5
6
7
8
while(1){
  a=cin.getline();
  if(a==Some_key){
     //Do stuff
  }else{
     // End loop
  }
}



If there is some universal solution for windows and linux that would be great. Also I would want to avoid some huge libraries if it would be possible.

Thank you
getasynckeystate() ?
if each pass through your loop can take 5 minutes it should really go on a background thread, otherwise you will hold up the entire UI for your application, the user cant even quit the app.

What do you display while it is happening? a dialog? if so, a cancel button would be useful.
If you dont display anything while its running it will look like your application has hung so something is better than nothing.
There is not much UI in this application. It is console program and it only prints which iteration step is currently running. And I don't want to quit this program before it finishes current loop.

What I try to do in the loop is Runge Kutta simulation - developemen of big grid made of "many molecules" in time. This grid is then saved to a file.

I only need some way to stop this looping if I think it takes too long. Killing the application from task manager just might corrupts my data.

I also found some solution to read console buffer (with SetConsoleMode and ReadConsoleInput) which might work but I didn't have much time to test it.
the generally accepted way to exit a console application is to use <CTRL-C> (break)

CTRL-C can be detected using Win32 calls.
https://msdn.microsoft.com/en-us/library/ms686016%28VS.85%29.aspx
closed account (2UD8vCM9)
If you want to check if the user pressed space you could do something like this
as long as you #include <Windows.h>
1
2
3
4
if (GetAsyncKeyState(VK_SPACE))
{
	//User pressed space
}


https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
Thank you for the good advices.
I will try it as soon as I have some time.
if (GetAsyncKeyState(VK_SPACE) & 0x8000)

*Fixed
OK, I tried some code if it is what I want but GetAsyncKeyState(VK_SPACE) is not good. The reason is I have to hold space all the time until the loop cycle passes this function. It doesn't react to key press.
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 <windows.h>
void doDelay()
{
    volatile unsigned int iii = 0;
    while(iii < 1000000000) {
        iii++;
    }
}
int main()
{
    int iteration = 0;
    bool flagLoop = true;

    while(flagLoop == true) {

        std::cout << iteration++ << '\n';
        doDelay();

        if(GetAsyncKeyState(VK_SPACE) & 0x8000) {
            flagLoop = false;
        }
    }
    std::cout << "loop stoped" << '\n';
}


Now, I also searched a liitle bit and found signal library. When I press ctrl+c it does what I want (end the loop and execute the rest of the code after the loop). Although, I really don't fully understand what this signal does and why it reacts only on ctrl+c and not any key press.
I only wanted to ask you if it is "good and safe" way to do things (for example in code where I have dynamic arrays, in code which is composed of multiple classes, use file IO, ...)
Does it have any effect on performance?
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
#include <iostream>
#include <csignal>

void doDelay(int number)
{
    std::cout << "delay " << number << '\n';

    volatile unsigned int iii = 0;
    while(iii < 100000000) {
        iii++;
    }
}

void doDelayLoop()
{
    for(int iii = 0; iii < 10; ++iii) {
        doDelay(iii);
    }
}

//Interrupt flag
bool flagLoop = true;
void raiseFlag(int param)
{
    flagLoop = false;
}

int main()
{
    signal(SIGINT, raiseFlag);

    //Keeping track of the current cycle
    int iteration = 0;

    //Infinite loop of the program
    while(flagLoop == true) {
        std::cout << "Iteration: " << iteration++ << '\n';
        doDelayLoop();
    }

    //After loop "clean-up"
    std::cout << "loop stoped" << '\n';
    doDelayLoop();
}

OK, I tried some code if it is what I want but GetAsyncKeyState(VK_SPACE) is not good. The reason is I have to hold space all the time until the loop cycle passes this function. It doesn't react to key press.


GetAsyncKeyState only responds to keypresses when you call it.

If you're not calling it in the time-consuming loop, then it won't poll the keystate until that loop exits.

Now, I also searched a liitle bit and found signal library. When I press ctrl+c it does what I want (end the loop and execute the rest of the code after the loop).


Ehhh.. I guess. I mean it is working exactly as you think it is, so I guess it's fine. But I don't know... for whatever reason this feels dirty to me. Maybe I'm just crazy. =P

Something like this could just as easily be accomplished with any kind of queued/buffered input. Like... a simple kbhit() call would probably work just as well without using signal handlers.

Although, I really don't fully understand what this signal does and why it reacts only on ctrl+c and not any key press.


Ctrl+C sends a special "user wants to abort" signal to the program. By calling the 'signal' function, you're saying "I want to catch that signal and treat it differently from the default behavior".

This is not really something that is meant to be used for normal program flow, it's really to be reserved for when things go horribly, horribly wrong and the user has no choice but to forcefully abort.

I only wanted to ask you if it is "good and safe" way to do things (for example in code where I have dynamic arrays, in code which is composed of multiple classes, use file IO, ...)


Safe? Yes, for the most part
Good? That's questionable.

The only thing that might be unsafe is that raiseFlag might be called by the signal handler from another thread (in fact, I'd imagine it'd have to be), which means you'd have to guard your flagLoop variable, either by making it atomic, or by putting access to it behind a mutex.


Does it have any effect on performance?


I doubt it. Your thread is still blasting away running at full speed, and you're not really having it do any extra work, so I doubt this will impact performance.
Topic archived. No new replies allowed.