Hi-res Program Time - c++

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.

Related

How can I wait for n seconds for a named pipe to open?

I have a program that I want to exit when I can not open a pipe for read, after N (lets say 30) seconds.
My code works with blocking name pipes and I can not change this.
I know about select() and poll() but I can not get them to work without turning my pipes into non-blocking.
This is my code so far:
struct pollfd fds[1];
int pol_ret;
fds[0].fd = open(pipe_name, O_RDONLY /* | O_NONBLOCK */);
if (fds[0].fd < 0)
{
// send_signal_to_parent();
std::cout << "error while opening the pipe for read, exiting!" << '\n';
return -1;
}
fds[0].events = POLLIN;
int timeout_msecs = 30000; // (30 seconds)
pol_ret = poll(fds, 1, timeout_msecs);
std::cout << "poll returned: "<< pol_ret << '\n';
if (pol_ret == 0)
{
std::cout << "im leaving" << '\n';
return -1;
}
How can I wait only for 30 seconds for a pipe to open for read?
I'm running Linux, debian in particular.
Setup up a timer with a signal handler and wait call open on the fifo.
If the open fails with errno=EINTR and your handler ran, the open call was interrupted by your timer, i.e., it timed out.
Example code:
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
volatile sig_atomic_t abort_eh;
void handler(int Sig)
{
abort_eh = 1;
}
int main()
{
struct sigaction sa;
sa.sa_flags = 0;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sigaction(SIGALRM,&sa,0);
//try to ensure the fifo exists
(void)mkfifo("fifo",0600);
//open with a timeout of 1s
alarm(1);
int fd;
do{
if (0>(fd=open("fifo",O_RDONLY)))
if(errno==EINTR){
if(abort_eh) return puts("timed out"),1;
else continue; //another signal interrupted it, so retry
}else return perror("open"),1;
}while(0);
alarm(0); //cancel timer
printf("sucessfully opened at fd=%d\n", fd);
}
setitimer or timer_create/timer_settime provide better more fine grained timers than alarm. They also have the possibility of setting the timer to repeat which allows you to resignal in case the first signal "missed" (i.e., ran just before the open call was entered and so failed to break the potentially indefinitely blocking syscall).

making auto timeout with std::cin statement

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

Pthread and keyboard

I want to know how to run a thread to sleep some time every time I press a key. For example, if I press the same key twice, it should have two threads to sleep for a while.
I MUST use pthreads and C++.
Honestly I have tried many ways but I still do not know how to solve it.
Sorry if my english is not very good :)
UPDATE
This is my code:
#include <pthread.h>
#include <iostream>
#include <unistd.h>
using namespace std;
pthread_mutex_t mutex;
pthread_cond_t cond;
int a;
void* executer2(void*)
{
pthread_mutex_lock(&mutex);
while (a > 0) {
pthread_cond_wait(&cond, &mutex);
}
cout << "Thread: " << pthread_self() << endl;
sleep(a);
pthread_mutex_unlock(&mutex);
}
void* executer(void*)
{
int key;
while (1) {
pthread_mutex_lock(&mutex);
key = cin.get();
if (key == 'a') {
cout << "Sleep for 4 seconds" << endl;
a = 4;
} else if (key == 'b') {
cout << "Sleep for 8 seconds" << endl;
a = 8;
} else {
cout << "Sleep for 2 seconds" << endl;
a = 2;
}
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
pthread_t tr, t;
pthread_attr_t attr;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&tr, &attr, executer, NULL);
pthread_create(&t, &attr, executer2, NULL);
pthread_join(tr, NULL);
pthread_join(t, NULL);
}
since you want to create a thread each time you press a key, and that the keypress handler is in executer, you should move the code to create executer2 in executer.
executer is made to sleep 1 sec. after reading a key press, but it seems that's not what you want. Just remove that call to sleep(1) to get an immediate response
the code of executer seems to indicate that you wish to modulate the time spent sleeping by the thread depending on the input key. You can pass the sleep time as a parameter to executer2, as indicated by the void * parameter of that function. The idea is to cast the time value to a void *, pass it at thread creation time, and cast it back to int within executer2:
// executer2 thread creation
pthread_create(&t, &attr, executer2,(void *)a);
and in executer2:
void *executer2(void *arg){
int a = (int)arg;
// ...
The thread creation code should go after the switch in executer2, and you should not need the global a variable anymore.
you are currently using a mutex to lock the code of executer2. This will prevent all the sleeping threads to sleep together at the same time. You will have to remove the lock to allow them to sleep concurrently (but leave the lock around the text output).
you say that you wish a C++ solution. You could benefit from using the thread library from the stl, which wraps the OS thread primitives (pthreads in your case) with higher level constructs and are easier to manipulate, especially for parameters. It would be a good exercise to convert your programme to use this library once you have the current code working.

Cancel a Call for User Input C++

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.

C++ select() not waiting for timeout period

I'm trying to use the select function to accept input but every 2 seconds do something else if the user hasn't entered anything. The code below is waiting two seconds the first time select() is reached but once it prints the first "timed out" message it rapidly keep printing out "timed out" without waiting for 2 seconds, basically entering an infinite loop. Anyone know what the problem is? Thanks for any help.
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
const int STDIN = 0;
int main(int argc, int *argv[])
{
struct timeval tv;
fd_set readfds, master;
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&master);
FD_SET(STDIN, &readfds);
FD_SET(STDIN, &master);
string buffer = "";
while(buffer != "quit"){
readfds = master;
if(select(STDIN+1, &readfds, NULL, NULL, &tv) == -1) perror("select");
if (FD_ISSET(STDIN, &readfds)){
getline(cin, buffer);
cout << "You entered: " << buffer << endl;
}else
cout << "Timed out.\n" << endl;
}
return 0;
}
per man: select() may update the timeout argument to indicate how much time was left. pselect() does not change this argument.
This implies that if it times out after 2 seconds it could set your tv_sec to 0.
If both of the fields of timeval are 0 it will return immediately.
Try setting your timeout every loop inside the while() to insure it's not getting overwritten.
I do some change based on your code, after select tv will be changed.
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
using namespace std;
const int STDIN = 0;
int main(int argc, int *argv[])
{
struct timeval tv,tv1;
fd_set readfds, master;
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&master);
FD_SET(STDIN, &readfds);
FD_SET(STDIN, &master);
string buffer = "";
while(buffer != "quit"){
readfds = master;
memcpy(&tv1, &tv, sizeof(tv));
if(select(STDIN+1, &readfds, NULL, NULL, &tv1) == -1) perror("select");
if (FD_ISSET(STDIN, &readfds)){
getline(cin, buffer);
cout << "You entered: " << buffer << endl;
}else
cout << "Timed out.\n" << endl;
}
return 0;
}
If you ever read the source of select.c in linux kernel, you'll find that in the select() call, the last parameter timeout will be set to zero after it is used.
So, you should set the value of tv inside the loop, before each call of select().
If memory serves, the call to select() can change the value of tv to indicate the time remaining. You should reinitialize tv before each call to select().
You must put
FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
into your loop. Assigning: readfds = master; will not always work (actually I'm pretty sure it will not work in every platform - depending on the definition of fd_et).
also setting tv in a loop is a good idea.