]> jfr.im git - irc/quakenet/newserv.git/blame - core/events-poll.c
merge
[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
54/*
55 * checkindex():
56 * Given the number of a new file descriptor, makes sure that the arrays
57 * will be big enough to deal with it.
58 */
59
60void checkindex(unsigned index) {
61 int oldmax=maxfds;
62
63 if (index<maxfds) {
64 return;
65 }
66
67 while (maxfds<=index) {
68 maxfds+=GROWFDS;
69 }
70
71 eventfds=(struct pollfd *)realloc((void *)eventfds,maxfds*sizeof(struct pollfd));
da846057 72 memset(&eventfds[oldmax],0,(maxfds-oldmax)*sizeof(struct pollfd));
2c5db955 73 eventhandlers=(reghandler *)realloc((void *)eventhandlers,maxfds*sizeof(reghandler));
da846057 74 memset(&eventhandlers[oldmax],0,(maxfds-oldmax)*sizeof(reghandler));
2c5db955
CP
75}
76
77/*
78 * registerhandler():
79 * Add an fd to the poll() array.
80 *
81 * Now O(1)
82 */
83
84int registerhandler(int fd, short events, FDHandler handler) {
85 checkindex(fd);
86
87 /* Check that it's not already registered */
88 if (eventhandlers[fd].handler!=NULL) {
89 return 1;
90 }
91
92 eventhandlers[fd].handler=handler;
93 eventhandlers[fd].fdarraypos=regfds;
94
95 eventfds[regfds].fd=fd;
96 eventfds[regfds].events=events;
97 eventfds[regfds].revents=0;
98
99 eventadds++;
100 regfds++;
101 return 0;
102}
103
104/*
105 * deregisterhandler():
106 * Remove an fd from the poll() array.
107 *
108 * The poll() version can't save any time if doclose is set, so
109 * we just do the same work and then close the socket if it's set.
110 *
111 * Now O(1)
112 */
113
114
115int deregisterhandler(int fd, int doclose) {
116 int oldfdpos;
117 int lastreggedfd;
118
119 /* Check that the handler exists */
120 if (eventhandlers[fd].handler==NULL)
121 return 1;
122
123 /* We need to rearrange the fds array slightly to handle the delete */
124 eventdels++;
125 regfds--;
126 if (regfds>0) {
127 oldfdpos=eventhandlers[fd].fdarraypos;
128 lastreggedfd=eventfds[regfds].fd;
129 if (lastreggedfd!=fd) {
130 /* We need to move the "lastreggedfd" into "oldfdpos" */
131 memcpy(&eventfds[oldfdpos],&eventfds[regfds],sizeof(struct pollfd));
132 eventhandlers[lastreggedfd].fdarraypos=oldfdpos;
133 }
134 }
135
136 eventhandlers[fd].handler=NULL;
137 eventhandlers[fd].fdarraypos=-1;
138
139 if (doclose) {
140 close(fd);
141 }
142
143 return 0;
144}
145
146/*
147 * handleevents():
148 * Call poll() and handle and call appropiate handlers
149 * for any sockets that come up.
150 *
151 * Unavoidably O(n)
152 */
153
154int handleevents(int timeout) {
155 int i,res;
156
157 for (i=0;i<regfds;i++) {
158 eventfds[i].revents=0;
159 }
160
161 res=poll(eventfds,regfds,timeout);
162 if (res<0) {
163 return 1;
164 }
165
166 for (i=0;i<regfds;i++) {
167 if(eventfds[i].revents>0) {
168 (eventhandlers[eventfds[i].fd].handler)(eventfds[i].fd, eventfds[i].revents);
169 eventexes++;
170 }
171 }
172 return 0;
173}
174
175void eventstats(int hooknum, void *arg) {
176 char buf[512];
c3db6f7e 177 long level=(long) arg;
2c5db955
CP
178
179 if (level>5) {
180 sprintf(buf,"Events :%7d fds registered, %7d fds deregistered",eventadds,eventdels);
181 triggerhook(HOOK_CORE_STATSREPLY,(void *)buf);
182 sprintf(buf,"Events :%7d events triggered, %6d fds active",eventexes,regfds);
183 triggerhook(HOOK_CORE_STATSREPLY,(void *)buf);
184 }
185}
186