1 #ifndef _event_api_H_
2 #define _event_api_H_
3 
4 /*
5   The API for the operating system dictates which events are
6   truly asyncronous.  Event needs C-level support only for
7   these types of events.
8  */
9 
10 typedef struct pe_watcher_vtbl pe_watcher_vtbl;
11 typedef struct pe_watcher pe_watcher;
12 typedef struct pe_event_vtbl pe_event_vtbl;
13 typedef struct pe_event pe_event;
14 typedef struct pe_ring pe_ring;
15 
16 struct pe_ring { void *self; pe_ring *next, *prev; };
17 
18 struct pe_watcher {
19     pe_watcher_vtbl *vtbl;
20     SV *mysv;
21     NV cbtime; /* float? XXX */
22     void *callback;
23     void *ext_data;
24     void *stats;
25     int running; /* SAVEINT */
26     U32 flags;
27     SV *desc;
28     pe_ring all;	/* all watchers */
29     pe_ring events;	/* this watcher's queued events */
30     HV *FALLBACK;
31     I16 refcnt;		/* internal to Event; not perl related */
32     I16 prio;
33     I16 max_cb_tm;
34 };
35 
36 struct pe_event {
37     pe_event_vtbl *vtbl;
38     SV *mysv;
39     pe_watcher *up;
40     U32 flags;
41     void *callback;
42     void *ext_data;
43     pe_ring peer; /* homogeneous */
44     pe_ring que;  /* heterogeneous */
45     I16 hits;
46     I16 prio;
47 };
48 
49 /* This must be placed directly after pe_watcher so the memory
50    layouts are always compatible. XXX? */
51 typedef struct pe_timeable pe_timeable;
52 struct pe_timeable {
53     pe_ring ring;
54     NV at;
55 };
56 
57 typedef struct pe_qcallback pe_qcallback;
58 struct pe_qcallback {
59     pe_ring ring;
60     int is_perl;
61     void *callback;
62     void *ext_data;
63 };
64 
65 /* PUBLIC FLAGS */
66 #define PE_REENTRANT	0x0008
67 #define PE_HARD		0x0010
68 #define PE_DEBUG	0x1000
69 #define PE_REPEAT	0x2000
70 #define PE_INVOKE1	0x4000
71 
72 #define WaFLAGS(ev)		((pe_watcher*)ev)->flags
73 
74 #define WaDEBUG(ev)		((WaFLAGS(ev) & PE_DEBUG)? 2:0) /*arthimetical*/
75 #define WaDEBUG_on(ev)		(WaFLAGS(ev) |= PE_DEBUG)
76 #define WaDEBUG_off(ev)		(WaFLAGS(ev) &= ~PE_DEBUG)
77 
78 #define WaREPEAT(ev)		(WaFLAGS(ev) & PE_REPEAT)
79 #define WaREPEAT_on(ev)		(WaFLAGS(ev) |= PE_REPEAT)
80 #define WaREPEAT_off(ev)	(WaFLAGS(ev) &= ~PE_REPEAT)
81 
82 #define WaREENTRANT(ev)		(WaFLAGS(ev) & PE_REENTRANT)
83 #define WaREENTRANT_on(ev)	(WaFLAGS(ev) |= PE_REENTRANT)
84 #define WaREENTRANT_off(ev)	(WaFLAGS(ev) &= ~PE_REENTRANT)
85 
86 #define WaHARD(ev)		(WaFLAGS(ev) & PE_HARD)
87 #define WaHARD_on(ev)		(WaFLAGS(ev) |= PE_HARD)   /* :-) */
88 #define WaHARD_off(ev)		(WaFLAGS(ev) &= ~PE_HARD)
89 
90 #define WaINVOKE1(ev)		(WaFLAGS(ev) & PE_INVOKE1)
91 #define WaINVOKE1_on(ev)	(WaFLAGS(ev) |= PE_INVOKE1)
92 #define WaINVOKE1_off(ev)	(WaFLAGS(ev) &= ~PE_INVOKE1)
93 
94 /* QUEUE INFO */
95 #define PE_QUEUES 7	/* Hard to imagine a need for more than 7 queues... */
96 #define PE_PRIO_HIGH	2
97 #define PE_PRIO_NORMAL	4
98 
99 /* io-ish flags */
100 #define PE_R 0x1
101 #define PE_W 0x2
102 #define PE_E 0x4
103 #define PE_T 0x8
104 
105 typedef struct pe_ioevent pe_ioevent;
106 struct pe_ioevent {
107     pe_event base;
108     U16 got;
109 };
110 
111 typedef struct pe_datafulevent pe_datafulevent;
112 struct pe_datafulevent {
113     pe_event base;
114     SV *data;
115 };
116 
117 typedef struct pe_idle pe_idle;
118 struct pe_idle {
119     pe_watcher base;
120     pe_timeable tm;
121     pe_ring iring;
122     SV *max_interval, *min_interval;
123 };
124 
125 typedef struct pe_io pe_io;
126 struct pe_io {
127     pe_watcher base;
128     pe_timeable tm; /*timeout*/
129     pe_ring ioring;
130     SV *handle;
131     void *tm_callback;
132     void *tm_ext_data;
133     float timeout;
134     U16 poll;
135     /* ifdef UNIX */
136     int fd;
137     int xref;  /*private: for poll*/
138     /* endif */
139 };
140 
141 typedef struct pe_signal pe_signal;
142 struct pe_signal {
143     pe_watcher base;
144     pe_ring sring;
145     IV signal;
146 };
147 
148 typedef struct pe_timer pe_timer;
149 struct pe_timer {
150     pe_watcher base;
151     pe_timeable tm;
152     SV *interval;
153 };
154 
155 typedef struct pe_var pe_var;
156 struct pe_var {
157     pe_watcher base;
158     SV *variable;
159     U16 events;
160 };
161 
162 typedef struct pe_group pe_group;
163 struct pe_group {
164     pe_watcher base;
165     NV since;
166     pe_timeable tm;
167     SV *timeout;
168     int members;
169     pe_watcher **member;
170 };
171 
172 typedef struct pe_generic pe_generic;
173 struct pe_generic {
174     pe_watcher base;
175     SV *source;
176     pe_ring active;
177 };
178 
179 typedef struct pe_genericsrc pe_genericsrc;
180 struct pe_genericsrc {
181     SV *mysv;
182     pe_ring watchers;
183 };
184 
185 typedef struct pe_event_stats_vtbl pe_event_stats_vtbl;
186 struct pe_event_stats_vtbl {
187     int on;
188     /* if frame == -1 then we are timing pe_multiplex */
189     void*(*enter)(int frame, int max_tm);
190     void (*suspend)(void *);
191     void (*resume)(void *);
192     void (*commit)(void *, pe_watcher *);  /* callback finished OK */
193     void (*scrub)(void *, pe_watcher *);   /* callback died */
194     void (*dtor)(void *);
195 };
196 
197 struct EventAPI {
198 #define EventAPI_VERSION 22
199     I32 Ver;
200 
201     /* EVENTS */
202     void (*queue   )(pe_event *ev);
203     void (*start   )(pe_watcher *ev, int repeat);
204     void (*now     )(pe_watcher *ev);
205     void (*stop    )(pe_watcher *ev, int cancel_events);
206     void (*cancel  )(pe_watcher *ev);
207     void (*suspend )(pe_watcher *ev);
208     void (*resume  )(pe_watcher *ev);
209 
210     /* All constructors optionally take a stash and template.  Either
211       or both can be NULL.  The template should not be a reference. */
212     pe_idle     *(*new_idle  )(HV*, SV*);
213     pe_timer    *(*new_timer )(HV*, SV*);
214     pe_io       *(*new_io    )(HV*, SV*);
215     pe_var      *(*new_var   )(HV*, SV*);
216     pe_signal   *(*new_signal)(HV*, SV*);
217 
218     /* TIMEABLE */
219     NV (*NVtime)();
220     void (*tstart)(pe_timeable *);
221     void (*tstop)(pe_timeable *);
222 
223     /* HOOKS */
224     pe_qcallback *(*add_hook)(char *which, void *cb, void *ext_data);
225     void (*cancel_hook)(pe_qcallback *qcb);
226 
227     /* STATS */
228     void (*install_stats)(pe_event_stats_vtbl *esvtbl);
229     void (*collect_stats)(int yes);
230     pe_ring *AllWatchers;
231 
232     /* TYPEMAP */
233     SV   *(*watcher_2sv)(pe_watcher *wa);
234     void *(*sv_2watcher)(SV *sv);
235     SV   *(*event_2sv)(pe_event *ev);
236     void *(*sv_2event)(SV *sv);
237     int   (*sv_2interval)(char *label, SV *in, NV *out);
238     SV   *(*events_mask_2sv)(int mask);
239     int   (*sv_2events_mask)(SV *sv, int bits);
240 
241     /* EVERYTHING ELSE */
242     void (*unloop)(SV *);
243     void (*unloop_all)(SV *);
244 };
245 
246 static struct EventAPI *GEventAPI=0;
247 
248 #define I_EVENT_API(YourName)						   \
249 STMT_START {								   \
250   SV *sv = perl_get_sv("Event::API",0);					   \
251   if (!sv) croak("Event::API not found");				   \
252   GEventAPI = (struct EventAPI*) SvIV(sv);				   \
253   if (GEventAPI->Ver != EventAPI_VERSION) {				   \
254     croak("Event::API version mismatch (%d != %d) -- please recompile %s", \
255 	  GEventAPI->Ver, EventAPI_VERSION, YourName);			   \
256   }									   \
257 } STMT_END
258 
259 #endif
260