aboutsummaryrefslogtreecommitdiff
path: root/runloop.c
blob: 30f28b2a889c79083e26b3f5e36fc06c9f41c7e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <string.h>
#include <errno.h>
#include <sys/select.h>
#include "runloop.h"


struct fd_list_item{
	int fd;
	runloop_callback *func;
};

static struct fd_list_item *fd_list;
static size_t fd_list_len,fd_list_cap;

__attribute__((constructor))
static void constructor(void){
	fd_list_cap=16;
	fd_list_len=0;
	fd_list=malloc(fd_list_cap,struct fd_list_item);
}


void runloop_add_fd(int fd,runloop_callback *func){
	if(fd_list_len==fd_list_cap){
		fd_list_cap*=2;
		fd_list=realloc(fd_list,fd_list_cap,struct fd_list_item);
	}
	fd_list[fd_list_len].fd=fd;
	fd_list[fd_list_len].func=func;
	fd_list_len++;
}

void runloop_run(void){
	while(true){
		fd_set inset;
		FD_ZERO(&inset);
		int maxfd=-1;
		for(size_t i=0;i<fd_list_len;i++){
			FD_SET(fd_list[i].fd,&inset);
			if(fd_list[i].fd>maxfd)maxfd=fd_list[i].fd;
		}
		int ret=select(maxfd+1,&inset,NULL,NULL,NULL);
		if(ret<=0){
			if(errno==EINTR)continue;
			die_perror("select");
		}
		for(size_t i=0;i<fd_list_len;i++){
			if(FD_ISSET(fd_list[i].fd,&inset)){
				if(fd_list[i].func(fd_list[i].fd)){
					memmove(fd_list+i,fd_list+i+1,(fd_list_len-i-1)*sizeof(struct fd_list_item));
					i--;
					fd_list_len--;
				}
			}
		}
	}
}