Reputation: 2815
I want to use select() to receive update from other server and also send out periodic messages. Consider the following set up:
while(1){ select(... timeout = 5 seconds); // some other code}
If I receive update at t = 2 seconds, then select() will return and corresponding statement will be executed. When the next loop begins, timeout will be set to 5 seconds again. However, it should be 5 - 2 = 3 seconds. Is there a way to update the timer with the right time?
I thought about to manually start a timer righr before select(), however this timer might not be synchronous with the one used in select(). And will cause other potential problems.
Upvotes: 2
Views: 2583
Reputation: 2862
When your app gets a little more complicated, you may have multiple timers with different timeout intervals. We do. Here is how we handle it.
Each timer has a timer object with a time_t of when the timer expires. We store all the timers in a heap data structure, so the soonest timer to expire is at the root of the heap. Before doing a select() we fetch the root of the heap, and subtract the current time from the timer's expiration time and use that delta as the timeout to the select() call.
Timer * t = heap->Root();
time_t now = time(0);
timeval tv;
tv.tv_sec = t->when - now;
tv.tv_usec = 0;
select( ... & tv );
Upvotes: 1
Reputation: 70422
According to the select
man page:
On Linux,
select()
modifies timeout to reflect the amount of time not slept; most other implementations do not do this. (POSIX.1-2001 permits either behaviour.)
So, you just simply reuse the timeout
variable. You only reset its value when you really time-out.
As the warning suggests, relying on this behavior makes for a porting problem, so if you rely on this behavior, make sure you document it so that the right thing is done when porting the code.
Upvotes: 3
Reputation: 1848
Just remember time()
in a variable before you call select()
, get another time()
when select()
returns and... in the next while(1)
iteration use not 5
, but 5 - difference_between_times
for timeout value.
Perhaps you'd want to use new_timeout = 5 - difference_between_times % 5
, so that if your operation after select
returns takes longer than 5 seconds... you still set the timeout
in 5 sec interval.
You probably should use not seconds, but some more granular time unit. And think whether above is the behaviour you really want (with modulo). Maybe when difference_between_times > 5
, you should wait just for 5 sec. Do as you wish, but you get the idea.
Upvotes: 1