]> jfr.im git - irc/quakenet/newserv.git/blame - core/events-poll.c
BUILD: add require-all build mode
[irc/quakenet/newserv.git] / core / events-poll.c
CommitLineData
2c5db955
CP
1/*
2 * events.c: the event handling core, poll() version
3 */
4
5#include <stdio.h>
6#include <sys/poll.h>
7#include <stdlib.h>
8#include <unistd.h>
9#include <string.h>
10
11#include "../lib/array.h"
12#include "events.h"
13#include "error.h"
14#include "hooks.h"
15
16typedef struct {
17 FDHandler handler;
18 int fdarraypos;
19} reghandler;
20
21/*
22 * OK, new data structure format for here to make everything
23 * faster. Two fixed static arrays, one of struct pollfds
24 * (for feeding to poll) in no particular order. Second array
25 * has an array of reghandler structs; this is indexed by FD for
26 * quick reference...
27 */
28
29struct pollfd *eventfds;
30reghandler *eventhandlers;
31
32unsigned int maxfds;
33
34int eventadds;
35int eventdels;
36int eventexes;
37
38/* How many fds are currently registered */
39int regfds;
40
41void eventstats(int hooknum, void *arg);
42
43void inithandlers() {
44 regfds=0;
45 eventadds=eventdels=eventexes=0;
46 maxfds=STARTFDS;
47 eventfds=(struct pollfd *)malloc(maxfds*sizeof(struct pollfd));
48 memset(eventfds,0,maxfds*sizeof(struct pollfd));
49 eventhandlers=(reghandler *)malloc(maxfds*sizeof(reghandler));
50 memset(eventhandlers,0,maxfds*sizeof(reghandler));
51 registerhook(HOOK_CORE_STATSREQUEST, &eventstats);
52}
53
4522b71a
P
54void finihandlers() {
55 deregisterhook(HOOK_CORE_STATSREQUEST, &eventstats);
56 free(eventfds);
57 free(eventhandlers);
58}
59
2c5db955
CP
60/*
61 * checkindex():
62 * Given the number of a new file descriptor, makes sure that the arrays
63 * will be big enough to deal with it.
64 */
65
66void checkindex(unsigned index) {
67 int oldmax=maxfds;
68
69 if (index<maxfds) {
70 return;
71 }
72
73 while (maxfds<=index) {
74 maxfds+=GROWFDS;
75 }
76
77 eventfds=(struct pollfd *)realloc((void *)eventfds,maxfds*sizeof(struct pollfd));
da846057 78 memset(&eventfds[oldmax],0,(maxfds-oldmax)*sizeof(struct pollfd));
2c5db955 79 eventhandlers=(reghandler *)realloc((void *)eventhandlers,maxfds*sizeof(reghandler));
da846057 80 memset(&eventhandlers[oldmax],0,(maxfds-oldmax)*sizeof(reghandler));
2c5db955
CP
81}
82
83/*
84 * registerhandler():
85 * Add an fd to the poll() array.
86 *
87 * Now O(1)
88 */
89
90int registerhandler(int fd, short events, FDHandler handler) {
91 checkindex(fd);
92
93 /* Check that it's not already registered */
94 if (eventhandlers[fd].handler!=NULL) {
95 return 1;
96 }
97
98 eventhandlers[fd].handler=handler;
99 eventhandlers[fd].fdarraypos=regfds;
100
101 eventfds[regfds].fd=fd;
102 eventfds[regfds].events=events;
103 eventfds[regfds].revents=0;
104
105 eventadds++;
106 regfds++;
107 return 0;
108}
109
110/*
111 * deregisterhandler():
112 * Remove an fd from the poll() array.
113 *
114 * The poll() version can't save any time if doclose is set, so
115 * we just do the same work and then close the socket if it's set.
116 *
117 * Now O(1)
118 */
119
120
121int deregisterhandler(int fd, int doclose) {
122 int oldfdpos;
123 int lastreggedfd;
124
125 /* Check that the handler exists */
126 if (eventhandlers[fd].handler==NULL)
127 return 1;
128
129 /* We need to rearrange the fds array slightly to handle the delete */
130 eventdels++;
131 regfds--;
132 if (regfds>0) {
133 oldfdpos=eventhandlers[fd].fdarraypos;
134 lastreggedfd=eventfds[regfds].fd;
135 if (lastreggedfd!=fd) {
136 /* We need to move the "lastreggedfd" into "oldfdpos" */
137 memcpy(&eventfds[oldfdpos],&eventfds[regfds],sizeof(struct pollfd));
138 eventhandlers[lastreggedfd].fdarraypos=oldfdpos;
139 }
140 }
141
142 eventhandlers[fd].handler=NULL;
143 eventhandlers[fd].fdarraypos=-1;
144
145 if (doclose) {
146 close(fd);
147 }
148
149 return 0;
150}
151
152/*
153 * handleevents():
154 * Call poll() and handle and call appropiate handlers
155 * for any sockets that come up.
156 *
157 * Unavoidably O(n)
158 */
159
160int handleevents(int timeout) {
161 int i,res;
162
163 for (i=0;i<regfds;i++) {
164 eventfds[i].revents=0;
165 }
166
167 res=poll(eventfds,regfds,timeout);
168 if (res<0) {
169 return 1;
170 }
171
172 for (i=0;i<regfds;i++) {
173 if(eventfds[i].revents>0) {
174 (eventhandlers[eventfds[i].fd].handler)(eventfds[i].fd, eventfds[i].revents);
175 eventexes++;
176 }
177 }
178 return 0;
179}
180
181void eventstats(int hooknum, void *arg) {
182 char buf[512];
c3db6f7e 183 long level=(long) arg;
2c5db955
CP
184
185 if (level>5) {
186 sprintf(buf,"Events :%7d fds registered, %7d fds deregistered",eventadds,eventdels);
187 triggerhook(HOOK_CORE_STATSREPLY,(void *)buf);
188 sprintf(buf,"Events :%7d events triggered, %6d fds active",eventexes,regfds);
189 triggerhook(HOOK_CORE_STATSREPLY,(void *)buf);
190 }
191}
192