How to Set Timeout for Std::Cin

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.

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.

How to implement timeout for function in c++

You can create a separate thread to run the call itself, and wait on a condition variable back in your main thread which will be signalled by the thread doing the call to f once it returns. The trick is to wait on the condition variable with your 1s timeout, so that if the call takes longer than the timeout you will still wake up, know about it, and be able to throw the exception - all in the main thread. Here is the code (live demo here):

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>

using namespace std::chrono_literals;

int f()
{
std::this_thread::sleep_for(10s); //change value here to less than 1 second to see Success
return 1;
}

int f_wrapper()
{
std::mutex m;
std::condition_variable cv;
int retValue;

std::thread t([&cv, &retValue]()
{
retValue = f();
cv.notify_one();
});

t.detach();

{
std::unique_lock<std::mutex> l(m);
if(cv.wait_for(l, 1s) == std::cv_status::timeout)
throw std::runtime_error("Timeout");
}

return retValue;
}

int main()
{
bool timedout = false;
try {
f_wrapper();
}
catch(std::runtime_error& e) {
std::cout << e.what() << std::endl;
timedout = true;
}

if(!timedout)
std::cout << "Success" << std::endl;

return 0;
}


Related Topics



Leave a reply



Submit