5

I have no idea of how to stop a program in middle can anyone help me i want my program to stop for a defined sec like 3sec or 6 sec and if you press any key it start running instantly.

An kit
  • 51
  • 2
  • 5
    `std::this_thread::sleep_for`, but it's unskippable. Unsure if there's a way in pure standard C++ to have a skippable delay. – HolyBlackCat Aug 30 '21 at 16:56
  • 1
    `select` on `STDIN` with a timeout of 3 or 6 seconds on the `select` statement. [Documentation for select](https://www.freebsd.org/cgi/man.cgi?select) – user4581301 Aug 30 '21 at 16:56
  • There's me thinking that `select` is supported on all platforms again. It's not. I'm pretty sure HBC is correct and there's no Standard-approved way to do this. – user4581301 Aug 30 '21 at 16:58
  • 2
    As mentioned, there's no standard C++ way of doing this. You need to use platform-specific functionality to "poll and sleep". Either `select` for POSIX systems (like Linux and macOS) or something else for Windows ([here's a list of Windows console function](https://learn.microsoft.com/en-us/windows/console/console-functions) which might help you). – Some programmer dude Aug 30 '21 at 17:00
  • 3
    The Windows approach would likely be based on [WaitForMultipleObjects](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitformultipleobjects). It waits on a 3 or 6 second timer and user input. – user4581301 Aug 30 '21 at 17:01
  • 2
    Could you add the target operating system? It's vital information for a useful answer. – user4581301 Aug 30 '21 at 17:10
  • I think your best bet is to use platform specific functions or use a somewhat portable library, like `pdcurses`. – Ted Lyngmo Aug 30 '21 at 17:10
  • Does this answer your question? [Sleep function in C++](https://stackoverflow.com/questions/1658386/sleep-function-in-c) – Gal Aug 30 '21 at 17:13
  • 1
    @Gal: In my opinion, your proposed duplicate is not a duplicate, because OP wants the wait to be interruptable. – Andreas Wenzel Aug 30 '21 at 17:17
  • 1
    @user4581301: Actually, [`WaitForSingleObject`](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject) should be sufficient in this case. You don't need to specify a separate timer object to wait for, as the function `WaitForSingleObject` allows you to specify a timeout in addition to the object to wait for. Therefore, when calling this function, it should be sufficient to specify a handle to the console input in addition to the timeout. – Andreas Wenzel Aug 30 '21 at 18:18
  • Yep. I overcomplicated. I almost never reach for `WaitForSingleObject ` because I'm almost never waiting for one thing, but it is definitely the better tool here. Any read-with-timeout will do the job, but there are none in Standard C++. – user4581301 Aug 30 '21 at 18:44

3 Answers3

3

As already stated in the comments section, there is no way to accomplish this in ISO C++. Therefore, you will have to revert to platform-specific functions.

On Microsoft Windows, you can use the function WaitForSingleObject to wait for console input and specify a timeout at the same time. That function will return as soon as there is new input or the timeout has expired. You can check the return value of the function in order to determine which one of these possibilities occurred.

On Linux, you can use select, poll or epoll to accomplish the same thing by waiting on the STDIN_FILENO file descriptor. However, that file descriptor will, by default, only provide new data for reading after the user presses ENTER. Therefore, you may want to disable canonical mode. An alternative may be to use ncurses, but I doubt that this library will be able to provide a file descriptor that is usable in select, poll or epoll. However, I am unfamiliar with ncurses.

EDIT: See the comments section for a very simple solution which uses ncurses.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • 1
    With curses is pretty simple. `initscr(); cbreak(); timeout(3000); int ch = getch(); if(ch == ERR) { /* timeout */ } else { /* key pressed within 3 seconds */ } endwin();` – Ted Lyngmo Aug 30 '21 at 19:53
0

Does this help you?

#include <iostream>
#include <unistd.h>
using namespace std;

int main()
{
    // Sleeping Mechanism
    for(auto i = 1; i <= 2; ++i)
    {
        cout << "Code pauses for 1 second\n";
        sleep(1); // Specify the number of seconds you want this block to sleep for
    }

    // Further code is executed once a particular key is pressed
    char ch;
    cin >> ch;
    while (ch != 'e')
    {
        cout << "Pressed " << ch << "\n";
        cin >> ch;
    }

    // Some code to be executed after pressing e only
    cout << "e pressed\n";
    return 0;
}

The second part where you wait for pressing a particular key is a workaround only and is not really a very good solution to what you are looking for.

Arun Suryan
  • 1,615
  • 1
  • 9
  • 27
  • 3
    I didn't downvote but I suspect that this doesn't do what OP asked for. The way I read the question is that the sleep should be aborted if any key is pressed while the sleep is performed. – Ted Lyngmo Aug 30 '21 at 17:16
  • Isn't this obvious from the code that both can be combined? – Arun Suryan Aug 30 '21 at 17:20
  • 3
    No, I don't see how that can be done using this answer as a base. – Ted Lyngmo Aug 30 '21 at 17:21
  • 2
    What you are suggesting does not work and the tools you are trying to combine cannot work together. You have a working idea, you could sleep tiny increments (but you can't do that with `sleep`. use `std::this_thread::sleep_for` kinda gets close) and then poll the keyboard for input (but you can't do that with `cin` because it always blocks). – user4581301 Aug 30 '21 at 18:30
0

You couldn't stop the entire process flow within the process. But there are some workarounds to stop the flow for a specific time:

Stop For A Specific Time

Using std:thread::sleep* Functions:

You can stop the entire running thread for/until a specific time using:

Stop For A Event

Using std::condition_variable:

If you want to sleep the entire running thread waiting for an event, you could use std::condition_variable:

Using The IO Operations:

Another option is to use some fake IO operations like a call to std::cin.get() (before calling you must ensure that std::cin buffer is empty)


Example

Here is a interruption with IO operation plus a time-out:

auto constexpr time_limit_s = 2;
input_value_t value = {' ', false};

auto const start_time = std::chrono::steady_clock::now();
std::thread read_input_thread(read_input_function, std::ref(value));

while (!value.read_flag && elapsed_time_from(start_time) < time_limit_s) {
        std::this_thread::yield();
}

if (!value.read_flag) {
        std::cout <<  "Timeout" << std::endl;
} else {
        std::cout <<  "Your value: " << value.value << std::endl;
}

Just for copy/paste and test: Read Input With Timeout

Ghasem Ramezani
  • 2,683
  • 1
  • 13
  • 32
  • 1
    A warning on this one: The lurking `std::cin.get();` in the full example can get you because it'll keep on lurking and will take data out of the stream sooner or later, probably at the worst possible time. – user4581301 Aug 30 '21 at 18:48
  • @user4581301 Sorry, I don't understand what you mean. – Ghasem Ramezani Aug 30 '21 at 19:03
  • 2
    If no one satisfies `std::cin.get()` before the timer expires you will still have a thread blocked on a read. Sooner or later the user is likely to type something else and that blocked read will consume part of it. – user4581301 Aug 30 '21 at 19:14