I wrote the program
#include<iostream>
using namespace std;
int n;
int main(int argc, char *argv[])
{
std::cout << "Before reading from cin" << std::endl;
// Below reading from cin should be executed within stipulated time
bool b=std::cin >> n;
if (b)
std::cout << "input is integer for n and it's correct" << std::endl;
else
std::cout << "Either n is not integer or no input for n" << std::endl;
return 0;
}
Here std::cin statement would wait for the console for input and will go for sleep mode until we provide some input and press Enter.
I want std::cin statement to go for timeout after 10 seconds(if user doesn't enter any data between 10 seconds then compiler would start executing the next statement of the program present below std::cin statement.
I am able to solve it using multithreading mechanism. Below is my code:
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<iostream>
using namespace std;
void *thread_function(void *arg);
int input_value;
int main(int argc, char *argv[])
{
int res;
pthread_t a_thread;
void *thread_result;
res=pthread_create(&a_thread,NULL,thread_function,NULL);
if(res!=0){
perror("Thread creation error");
exit(EXIT_FAILURE);
}
//sleep(10);
cout<<"cancelling thread"<<endl;
res=pthread_cancel(a_thread);
cout<<"input value="<<input_value<<endl;
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
int res;
res=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
if(res!=0){
perror("Unable to set pthread to cancel enbable state");
exit(EXIT_FAILURE);
}
cin>>input_value;
pthread_exit(&input_value);
}
But here I am facing a problem. Due to the sleep function either user inputs value or not the sleep function by default sleeps for 10 seconds. This is where I am lagging.
How do I solve this problem like using(signals,binary semaphores etc..). Please relate your answer w.r.t my solution(i.e multithreading).
Any information is most welcome...
Since you're on a POSIX machine, you can use e.g. select to check if there's anything on the standard input:
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds)
timeval timeout;
timeout.tv_sec = 5; // A five-second timeout
timeout.tv_usec = 0;
int rc = select(STDIN_FILENO + 1, &fds, nullptr, nullptr, &timeout);
if (rc < 0)
perror("select");
else if (rc == 0)
{
// Timeout
}
else
{
// There is input to be read on standard input
}
Using poll (as suggested by Basile Starynkevitch) it could be done something like this:
struct pollfd poller;
poller.fd = STDIN_FILENO;
poller.events = POLLIN;
poller.revents = 0;
int rc = poll(&poller, 1, 5); // Poll one descriptor with a five second timeout
if (rc < 0)
perror("select");
else if (rc == 0)
{
// Timeout
}
else
{
// There is input to be read on standard input
}
I've tried a few solutions to get this to work and my current solution is pretty hacky, however, it works for my where the other solutions here using select and poll have failed.
My code would sometimes give me a positive result for data being available but then block forever on std::cin.get(); or std::getline(std::cin, STRINGVARIABLE);
My solution:
// Reset flag, initially true so that if cin blocks it will be reset
bool Reset = true;
// Create a c++11 thread to reset cin after a timeout of 100ms
std::thread ResetThread([&Reset](void){
// This thread will wait 100ms
std::this_thread::sleep_for(std::chrono::milliseconds(100));
// Then if the reset flag is still true it will reset cin by closing and opening it
if (Reset) {
close(STDIN_FILENO);
// TODO: Really the output of this open call should be checked for errors
open("/dev/null", O_RDONLY);
}
});
// Now for the standard reading of cin:
std::string Line;
std::getline(std::cin, Line);.
// If cin was read correctly the getline command will return immediately
// This means that the reset flag will be set to false long before the thread tests it.
Reset = false;
// Finally join with the thread.
ResetThread.join();
This code can be joined with the select or poll methods (it is in my code) to prevent creating a new thread every 100ms.
Obviously the appropriateness of this code will depend on the rest of your project, but it works for me so I thought I'd share.
-- EDIT --
After moving between PCs it seems that this code isn't as robust as I'd hoped. I've now accepted just using a separate blocked thread for input, see my answer here:
After fighting with non-blocking cin for a long time it seems the only robust way of doing it is inside its own thread.
See my answer here for an implementation:
https://stackoverflow.com/a/39499548/1427932
Related
Is it possible to set timeout for std::cin?
For example, std::cin doesn't receive any data during 10 seconds - it throws an exception or returns an error.
Edited:
And what about timer from Boost library? As far as I know, it is portable library. Is it possible to ask timer of Boost library to throw exceptions after predefined period of time? I guess it can solve this problem.
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.
I just figured out how to do that, polling the std::cin file descriptor.
poll function returns 0 if timeout occurs and no event happened, 1 if something happened, and -1 if error happened.
#include <iostream>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
bool stop = false;
void intHandler(int dummy)
{
stop = true;
}
std::string readStdIn()
{
struct pollfd pfd = { STDIN_FILENO, POLLIN, 0 };
std::string line;
int ret = 0;
while(ret == 0)
{
ret = poll(&pfd, 1, 1000); // timeout of 1000ms
if(ret == 1) // there is something to read
{
std::getline(std::cin, line);
}
else if(ret == -1)
{
std::cout << "Error: " << strerror(errno) << std::endl;
}
}
return line;
}
int main(int argc, char * argv[])
{
signal(SIGINT, intHandler);
signal(SIGKILL, intHandler);
while(!stop)
{
std::string line = readStdIn();
std::cout << "Read: " << line << std::endl;
}
std::cout << "gracefully shutdown" << std::endl;
}
There was a good answer posted here but the author removed it. It's a solution that worked well for me in the application I was developing. This is the essence of what the person wrote:
// compile: g++ -pthread thisfile.cpp
#include <iostream>
#include <thread>
int main() {
int x;
bool inputReceived = false;
time_t startTime = time(NULL);
time_t waitTime = 10;
std::cout << "Enter a number within " << waitTime << " seconds\n";
// spawn a concurrent thread that waits for input from std::cin
std::thread t1([&]() {
std::cin >> x;
inputReceived = true;
});
t1.detach();
// check the inputReceived flag once every 50ms for 10 seconds
while (time(NULL) < startTime + waitTime && !inputReceived) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
if (inputReceived) {
std::cout << "x = " << x << "\n";
return EXIT_SUCCESS;
}
std::cout << "timeout\n";
// TODO: find a way to kill the thread
return EXIT_FAILURE;
}
Be aware that the thread continues running after the timeout occurs, but it will terminate when the whole program terminates. If this is all you need then you don't need to worry about it.
However, there is no simple way to kill a detached thread. A solution would be to close the input stream, but that's not easy or desirable to do with std::cin. If you're lucky then you're going to use this with an easily closeable stream instead of std::cin. Closing the stream will cause input statement to fail and the the thread will probably just exit with an internal exception, but at least the thread will terminate.
I have a C++ function here:
void printTextSlowly(string &s, int speed)
{
int position = 0;
for(char c: s)
{
position++;
std::this_thread::sleep_for(std::chrono::milliseconds(speed));
std::cout << c << std::flush;
// Should run until user presses enter.
//if(cin.ignore())
//{
// std::string subString = s.substr(position);
// std::cout << subString << std::endl;
// break;
//}
}
}
So basically this will slow the text down which it does but when user presses enter, it should stop and print out the rest of the text. With cin.ignore() it waits for the user to do something. I don't want it to wait.
Help is greatly appreciated.
Edit: select is obsolete. Use pool instead
What you want is to wait for a specific amount of time or until you have something on stdin.
Since you are on linux this can be achieved with select.
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
select() and pselect() allow a program to monitor multiple file
descriptors, waiting until one or more of the file descriptors become
"ready" for some class of I/O operation
You don't need multiple file selectors. Just stdin. And set the timeout to 1 millisecond.
Since I don't have a linux handy here is some untested code adapted from the linked page example and your example:
fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin to see when it has input. */
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
/* Wait 1 millisecond. */
tv.tv_sec = 0;
tv.tv_usec = 1000;
int position = 0;
for (int position = 0; position < s.length(); ++position)
{
retval = select(1, &rfds, nullptr, nullptr, &tv);
if (retval == -1)
{
perror("select()");
// exit or throw or deal with error
}
else if (retval)
{
// Data available on cin (user pressed enter)
std::string subString = s.substr(position);
std::cout << subString << std::endl;
break;
}
else
{
// No data on cin, continue printing
std::cout << s[position] << std::flush;
}
}
1) Copy the String in a new variable(until it got printed).
2) Use a do-while loop until user presses enter.
3) Find out the remaining string and print after ending the do-while loop.
Hope it helps :)
I have following code in my chat client:
fd_set fds;
struct timeval t;
t.tv_sec = 0;
t.tv_usec = 100;
int ret;
string message;
while(run)
{
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
if((ret = select(STDIN_FILENO + 1, &fds, NULL, NULL, &t)) < 0)
{
exit(ERR_SELECT);
}
else if(ret > 0 && FD_ISSET(STDIN_FILENO, &fds))
{
message.clear();
getline(cin, message);
if(strlen(message.c_str()) > 0)
{
send_message(&message, client_socket);
}
}
}
It works fine when I type something while program is running. It reads message in stdin, sends it and then wait in loop for next input. But when I pass input to program on start like this:
echo "message" | ./chat_client
Or this:
printf "message\n" | ./chat_client
It reads and sends "message" but then in next iterations of loop it behaves like there is something in stdin but getline reads only empty string. And then when I write something, getline does not read it.
Does anyone know what causes it?
Thanks for any advice
getline() returns if it reaches end-of-file, which happens when everything coming from the pipe has been read. You need to explicitly test if cin.eof() returns true.
As for select() it's by design that it shows the file as "readable" if at end-of-file. That way the program can detect the connection was closed. The Linux manual for select() states that:
A file descriptor is considered ready if it is possible to perform a
corresponding I/O operation (e.g., read(2) without blocking...
and a read() on a file descriptor at EOF returns a zero without blocking.
I'm not sure if you can get problems by selecting on an fd read through an istream, but this works for me (Linux/gcc):
#include <iostream>
#include <sys/select.h>
#include <unistd.h>
int main()
{
std::string message;
while(1) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
int ret = select(1, &fds, NULL, NULL, NULL);
if (ret == -1) break;
getline(std::cin, message);
if (std::cin.eof()) {
std::cout << "eof." << std::endl;
break;
}
std::cout << "read: " << message << std::endl;
}
return 0;
}
How would I effectively cancel a call for user input if there is no input within a certain time? (I'm programming a game for a terminal/cmd window with Mac OS X).
I have tried turning off canonical buffering and using a timer thread that joins after the call for user input. I also tried implementing the call to pthread_join() within the parameters of the while loop. Still nothing. The problem is that even though canonical buffering is off, the call for user input is still held up when there is no input. It works fine if there is input though.
It would be great if I could do this without fiddling around with downloading and installing ncurses, but I'll do it if I have to.
Edit: Source code:
//Most headers only pertain to my main program.
#include <iostream>
#include <termios.h>
#include <pthread.h>
#include <time.h>
#include <cstring>
#include <stdio.h>
#include <string.h>
using namespace std;
//Timer function.
void *Timer(void*) {
time_t time1, time2;
time1 = time(NULL);
while (time2 - time1 < 1) {
time2 = time(NULL);
}
pthread_exit(NULL);
}
int main() {
//Remove canonical buffering.
struct termios t_old, t_new;
tcgetattr(STDIN_FILENO, &t_old);
t_new = t_old;
t_new.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &t_new);
cout << "Press any key to continue." << endl;
string szInput;
int control = 0;
do {
pthread_t inputTimer;
pthread_create(&inputTimer, NULL, Timer, NULL);
szInput = "";
while (szInput == "") {
szInput = cin.get();
//Handle keypresses instantly.
if (szInput == "a") {
cout << endl << "Instant keypress." << endl;
}
}
pthread_join(inputTimer, NULL);
cout << endl << "One second interval." << endl;
control ++;
} while (control < 25);
cout << "Game Over." << endl;
return 0;
}
See if this works!
char ch; //Input character
int time = 0; //Time iterator
int TIMER = 5000; //5 seconds
while(time<TIMER)
{
if(!kbhit())
{
time = 0;
ch = getch();
//Do your processing on keypress
}
time++;
delay(1);
}
kbhit() detects if any keystroke has occurred. If yes, then get the key character in ch.
One way of checking if there is input is to poll the file descriptor STDIN_FILENO using e.g. the select system call. If STDIN_FILENO is readable, then you can read at at least one character. You can also pass a timeout to the select call.
Thanks Shashwat, it works with the below modifications:
1) Changing if(!kbhit()) to if(kbhit())
2) Changing delay(1); to Sleep(1);
I do not have enough rep to post a comment, hence adding as an answer.
I'm currently programming Tetris in C++. Right now I am at the stage where I have finished writing the program but I still need to fix a few bugs and optimize performance.
That being said, one of the flaws in my program is that it can only handle one key-press per second. I need it to handle at least three. You can see the flaw demonstrated by this code:
//Most headers only pertain to my main program.
#include <iostream>
#include <termios.h>
#include <pthread.h>
#include <time.h>
#include <cstring>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
//Timer function.
void *Timer(void*) {
time_t time1, time2;
time1 = time(NULL);
while (time2 - time1 < 1) {
time2 = time(NULL);
}
pthread_exit(NULL);
}
int main() {
//Remove canonical buffering.
struct termios t_old, t_new;
tcgetattr(STDIN_FILENO, &t_old);
t_new = t_old;
t_new.c_lflag &= (~ICANON & ~ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &t_new);
const int STDIN = 0;
struct timeval tv, tv1;
fd_set readfds, readfds2, master;
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&master);
FD_SET(STDIN, &readfds);
FD_SET(STDIN, &master);
char buffer[1];
while(buffer[0] != 'q') {
pthread_t inputTimer;
pthread_create(&inputTimer, NULL, Timer, NULL);
readfds = master;
memcpy(&tv1, &tv, sizeof(tv));
if (select(STDIN+1, &readfds, NULL, NULL, &tv1) == -1) {
perror("select");
}
if (FD_ISSET(STDIN, &readfds)) {
buffer[0] = cin.get();
cout << "You entered: " << buffer << endl;
}
pthread_join(inputTimer, NULL);
cout << "Timed out.\n" << endl;
}
cout << "Game Over." << endl;
return 0;
}
As you can see, the program operates by setting up a one second interval timer and timeval. Because both timers use ints to determine how much time has passed, they cannot be more precise than one second. How can I modify my program to be more precise?
My thought was to copy the value of tv1 to a third value if a key was pressed and then wait for input again but for whatever value time that tv1 was. For example if I press a key when there is only half a second left, the value 0.5 would be taken from tv1 and copied to another variable. Then the program would only wait for half a second for input, instead of the full second. This didn't work, however, because tv1 only ever equals 1 or 0.
Try to use struct timeval and gettimeofday() in sys/time.h. You can achieve microseconds resolution.
Manpage: http://linux.die.net/man/3/gettimeofday
Further info: http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
EDIT:
In Linux (not portable to MinGW under Windows) you could also use poll() (see here), which lets you wait for milliseconds. That would be more efficient because poll suspends the thread execution until time is out.
//Timer function.
void *Timer(void*) {
poll(0, 0, 100); //Suspend thread for 100 ms.
pthread_exit(NULL);
}
The pollfunction is declared in poll.h
The problem here is that pthread_join suspends the main thread until the timer thread completes. You will therefore miss any user input that comes during or after the join. Since you are already using select, you might as well make use of the timeout built into the select statement. If you keep a watch of time elapsed, you can achieve the same effect without the timer thread.