Created
September 29, 2021 17:17
-
-
Save mppf/4bf1c0c78309107b887234986c341d39 to your computer and use it in GitHub Desktop.
libevent timeout across multiple event_add
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Program to demonstrate managing total timeout across many | |
event_add calls. | |
It accepts input on stdin for 2 seconds and demonstrates running | |
for 2 seconds whether there is input or not. | |
*/ | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <signal.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <event2/bufferevent.h> | |
#include <event2/buffer.h> | |
#include <event2/listener.h> | |
#include <event2/util.h> | |
#include <event2/event.h> | |
static void callback(evutil_socket_t, short, void *); | |
struct mystate { | |
struct event_base *base; | |
struct event *e; | |
struct timeval start_time; | |
struct timeval timeout; | |
}; | |
void setnonblocking(int fd) { | |
int opt; | |
opt = fcntl(fd, F_GETFL); | |
if (opt < 0) { | |
printf("fcntl(F_GETFL) fail."); | |
} | |
opt |= O_NONBLOCK; | |
if (fcntl(fd, F_SETFL, opt) < 0) { | |
printf("fcntl(F_SETFL) fail."); | |
} | |
} | |
int | |
main(int argc, char **argv) | |
{ | |
struct mystate s = {0}; | |
setbuf(stdin, NULL); | |
setnonblocking(0); | |
s.base = event_base_new(); | |
if (!s.base) { | |
fprintf(stderr, "Could not initialize libevent!\n"); | |
return 1; | |
} | |
s.e = event_new(s.base, /* stdin */ 0, EV_READ, callback, &s); | |
s.timeout.tv_sec = 2; | |
event_base_gettimeofday_cached(s.base, &s.start_time); | |
event_add(s.e, &s.timeout); | |
event_base_dispatch(s.base); | |
return 0; | |
} | |
static | |
int timeval_subtract(struct timeval *result, | |
struct timeval *x, | |
struct timeval *y) | |
{ | |
result->tv_sec = x->tv_sec - y->tv_sec; | |
if ((result->tv_usec = x->tv_usec - y->tv_usec) < 0) | |
{ | |
result->tv_usec += 1000000; | |
result->tv_sec--; // borrow | |
} | |
return result->tv_sec < 0; | |
} | |
static void | |
callback(evutil_socket_t sig, short events, void *user_data) | |
{ | |
struct mystate* s = (struct mystate*) user_data; | |
unsigned char buf[64]; | |
ssize_t got = 0; | |
struct timeval now = {0}; | |
struct timeval elapsed = {0}; | |
struct timeval remaining = {0}; | |
event_base_gettimeofday_cached(s->base, &now); | |
if ((events & EV_TIMEOUT) != 0) { | |
printf("callback for timeout -- breaking\n"); | |
event_base_loopbreak(s->base); | |
} else { | |
printf("callback for read\n"); | |
// read some data | |
got = read(0, buf, sizeof(buf)); | |
// compute how much time is left and schedule an event | |
timeval_subtract(&elapsed, &now, &s->start_time); | |
timeval_subtract(&remaining, &s->timeout, &elapsed); | |
if (remaining.tv_sec < 0) { | |
remaining.tv_sec = 0; | |
remaining.tv_usec = 0; | |
} | |
printf("remaining usecs: %li\n", | |
((long int)remaining.tv_sec)*1000000 + remaining.tv_usec); | |
event_add(s->e, &remaining); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment