I have following code, but it is not ending the while
loop even if done
is true. It keeps waiting for _getch()
:
while (done || ((c = _getch()) != EOF))
{
cout << "Operation aborted" << endl;
break;
}
cout << "Operation finished" << endl;
Edit: In fact i want to be able to interrupt a long operation performed in another thread. I believe I have to join thread after while
loop. But with the following code, the loop is not getting executed when I press a key.
thread t(Start, folder_path);
while (done || ((c = _getch()) != EOF))
{
cout << "Operation aborted" << endl;
exit_signal.set_value();
break;
}
t1.join();
cout << "Operation finished" << endl;
How can I end the loop when done
is true ?
The loop conditions is written in a way that:
done
is true, the logical expression is short circuited and the loop body is entered without evaluating the right side of the condition. done
is false, then _getch()
is called. If there is a char returned, the expression will be true, and the loop body is entered. If there's no char available, _getch()
will wait until the user types one. Only if the end-of-file is encountered (i.e. Ctrl+Z is entered in terminal mode, or cin is redirected from a file and its end is reached), will the loop be interrupted. If you wanted a non-blocking keyboard entry, you'd have to use _kbhit()
first, to check if a char is available, and then only read the char with _getch()
. For kbhit()
on linux, you may have a look here.
Edit: your multithreading edit
First of all, if done
is a variable that is used in both threads (which apparently it is, since it's not changed in the loop), make sure that it it declared atomic
. If this is not the case, you'd have a race condition that is UB.
Now, your narrative doesn't match the code. If done
is when the other thread has finished, and you want to end the loop at this moment, you'd need to loop on !done
.
Furthermore, if you want to loop as long as the other thread is running, but check the keyboard and let the user interrupt the code, you'd better do that check in the loop. By the way, it could be an option to go sleep_for
a couple of milliseconds in the loop body, in order to avoid wasting to much CPU for querying the keyboard.
So the code would end up with a structure like
std::atomic<bool> done(false);
...
thread t(Start, folder_path);
while (!done)
{
if (_kbhit() && ((c = _getch()) != EOF) { // if keystroke available
cout << "Operation aborted" << endl;
exit_signal.set_value(); // assuming this would make t1 return from folder_path()
break;
}
std::this_thread::sleep_for (std::chrono::milliseconds(500));
// update status bar or do other stuff
}
t1.join();
cout << "Operation finished" << endl;
Finally, I don't know what exit_signal.set_value();
is doing. I hope it does do something that tells the other thread to stop the processing. If it doesn't, your loop would finish, but at the join()
you'd anyway have to wait for the other thread to complete.