How to Make Reading from 'Std::Cin' Timeout After a Particular Amount of Time

Is it possible to set timeout for std::cin?

It isn't possible to set a time out for std::cin in a portable way. Even when resorting to non-portable techniques, it isn't entirely trivial to do so: you will need to replace std::cin's stream buffer.

On a UNIX system I would replace the default stream buffer used by std::cin by a custom one which uses file descriptor 0 to read the input. To actually read the input I would use poll() to detect presence of input and set a timeout on this function. Depending on the result of poll() I would either read the available input or fail. To possibly cope with typed characters which aren't forwarded to the file descriptor, yet, it may be reasonable to also turn off the buffering done until a newline is entered.

When using multiple threads you can create a portable filtering stream buffer which uses on thread to read the actual data and another thread to use a timed condition variable waiting either for the first thread to signal that it received data or for the time out to expire. Note that you need to guard against spurious wake-ups to make sure that the timeout is indeed reached when there is no input. This would avoid having to tinker with the actual way data is read from std::cin although it still replaces the stream buffer used by std::cin to make the functionality accessible via this name.

Is it possible to bypassing std::cin after a specified amount of time?

I'm pretty sure there's nothing that's even close to portable. For that matter, there's probably nothing that works directly with iostreams.

Given that you want it for Windows, you could use the console API directly. In particular, you can use WaitForSingleObject on the standard input handle, and give a timeout:

HANDLE standard_input = GetStdHandle(STD_INPUT_HANDLE);

if (WaitForSingleObject(standard_input, 5000) == WAIT_OBJECT_0)
// read what the user entered
else
// timed out (or otherwise failed).

Input with a timeout in C++

What you are trying to do is to have an non-blocking (asynchronous) read from stdin with a timeout of 10 seconds. This is not too tough but may involve many new concepts depending on your current level.

The key concept here is that cin >> password; is a blocking call, i.e., until it is completed, control will not flow further in this code. So we need to make it non-blocking in some way, or keep it blocking and break out of it when the timeout expires.

There are a few common implementations based on the design requirements and constraints of the system. Each implementation is different depending on the OS but the techniques are very similar.

1. Asynchronous: STDIN with timeout
This approach is commonly used in network programming and can be extended to other forms of input such as the current case.

  1. Place the standard input (STDIN) handle (handle = 0) into a 'watch-list'.
  2. Place a timeout on the watch-list.
  3. Whenever there is a change in the STDIN, process it.
  4. When the timeout has expired, check if what we have processed does the job.

In Linux (and many other Unix flavors), the watch-list can be handled using FD_SET and a select system call. In Windows, you will need to use WaitForMultipleEvents.

I'm not sure I can do justice to explaining these concepts accurately for the purposes of this question. As a reference, another question which has some code pointers for exactly the same thing is here.

2. Synchronous: Multithreaded with Interrupt
This is a common technique used for cases where we need a fine-grained event-scheduler / timer.

  1. Create two threads, A and B.
  2. A will wait on the indicated timeout.
  3. B will wait on a blocking read
  4. If A terminates (times out) before B finishes, A signals B and B decides what to do next (terminate, repeat a message etc)
  5. If B reads the password and it's fine, B signals A and asks it to die.

Another way to achieve the same is to make the OS interrupt thread B as described in one of the comments.

3. Synchronous: Polling
This is used for cases where we don't need too much of a fine-grained control over time.

  1. Check if there is anything in the input using a non-blocking read (kbhit())
  2. If there is none, and if there is time remaining in the timeout, wait for a smaller amount of time delta (say 10ms)
  3. If the timeout has expired and there is no more time remaining, do whatever processing is needed (message the user, exit etc)

Note that in this case, depending on the delta, the approach may consume a lot of CPU and may be inefficient. For example, if delta=10ms as above, the thread will be woken up 100 times every second and it will be not efficient, especially when users do not type characters on their keyboard that fast.



Related Topics



Leave a reply



Submit