1 #include "EventAPI.h"
2 
3 #define PE_NEWID ('e'+'v')  /* for New() macro */
4 
5 #define PE_RING_INIT(LNK, SELF) 		\
6 STMT_START {					\
7   (LNK)->next = LNK;				\
8   (LNK)->prev = LNK;				\
9   (LNK)->self = SELF;				\
10 } STMT_END
11 
12 #define PE_RING_EMPTY(LNK) ((LNK)->next == LNK)
13 
14 #define PE_RING_UNSHIFT(LNK, ALL)		\
15 STMT_START {					\
16   assert((LNK)->next==LNK);			\
17   (LNK)->next = (ALL)->next;			\
18   (LNK)->prev = ALL;				\
19   (LNK)->next->prev = LNK;			\
20   (LNK)->prev->next = LNK;			\
21 } STMT_END
22 
23 #define PE_RING_ADD_BEFORE(L1,L2)		\
24 STMT_START {					\
25   assert((L1)->next==L1);			\
26   (L1)->next = L2;				\
27   (L1)->prev = (L2)->prev;			\
28   (L1)->next->prev = L1;			\
29   (L1)->prev->next = L1;			\
30 } STMT_END
31 
32 #define PE_RING_DETACH(LNK)			\
33 STMT_START {					\
34   if ((LNK)->next != LNK) {			\
35     (LNK)->next->prev = (LNK)->prev;		\
36     (LNK)->prev->next = (LNK)->next;		\
37     (LNK)->next = LNK;				\
38   }						\
39 } STMT_END
40 
41 /* too bad typeof is a G++ specific extension
42 #define PE_RING_POP(ALL, TO)			\
43 STMT_START {					\
44   pe_ring *lk = (ALL)->prev;			\
45   PE_RING_DETACH(lk);				\
46   TO = (typeof(TO)) lk->self;			\
47 } STMT_END
48 */
49 
50 typedef struct pe_cbframe pe_cbframe;
51 struct pe_cbframe {
52     pe_event *ev;
53     IV run_id;
54     void *stats;
55 };
56 
57 typedef struct pe_tied pe_tied;
58 struct pe_tied {
59     pe_watcher base;
60     pe_timeable tm;
61 };
62 
63 #define WKEYMETH(M) static void M(pe_watcher *ev, SV *nval)
64 #define EKEYMETH(M) static void M(pe_event *ev, SV *nval)
65 
66 /* When this becomes a public API then we should also publish C interfaces
67    to set up perl & C callbacks.  For now we can be lazy. */
68 struct pe_event_vtbl {
69     HV *stash;
70     pe_event *(*new_event)(pe_watcher *);
71     void (*dtor)(pe_event *);
72 
73     pe_ring freelist;
74 };
75 
76 struct pe_watcher_vtbl {
77     int did_require;
78     HV *stash;
79     void (*dtor)(pe_watcher *);
80     char*(*start)(pe_watcher *, int);
81     void (*stop)(pe_watcher *);
82     void (*alarm)(pe_watcher *, pe_timeable *);
83     pe_event_vtbl *event_vtbl;
84     pe_event *(*new_event)(pe_watcher *);
85 };
86 
87 #define PE_ACTIVE	0x001
88 #define PE_POLLING	0x002
89 #define PE_SUSPEND	0x004
90 #define PE_PERLCB	0x020
91 #define PE_RUNNOW	0x040
92 #define PE_TMPERLCB	0x080
93 #define PE_CANCELLED	0x400
94 #define PE_DESTROYED	0x800
95 
96 #define PE_VISIBLE_FLAGS (PE_ACTIVE | PE_SUSPEND)
97 
98 #ifdef DEBUGGING
99 #  define WaDEBUGx(ev) (SvIV(DebugLevel) + WaDEBUG(ev))
100 #else
101 #  define WaDEBUGx(ev) 0
102 #endif
103 
104 /* logically waiting for something to happen */
105 #define WaACTIVE(ev)		(WaFLAGS(ev) & PE_ACTIVE)
106 #define WaACTIVE_on(ev)		(WaFLAGS(ev) |= PE_ACTIVE)
107 #define WaACTIVE_off(ev)	(WaFLAGS(ev) &= ~PE_ACTIVE)
108 
109 /* physically registered for poll/select */
110 #define WaPOLLING(ev)		(WaFLAGS(ev) & PE_POLLING)
111 #define WaPOLLING_on(ev)	(WaFLAGS(ev) |= PE_POLLING)
112 #define WaPOLLING_off(ev)	(WaFLAGS(ev) &= ~PE_POLLING)
113 
114 #define WaSUSPEND(ev)		(WaFLAGS(ev) & PE_SUSPEND)
115 #define WaSUSPEND_on(ev)	(WaFLAGS(ev) |= PE_SUSPEND)
116 #define WaSUSPEND_off(ev)	(WaFLAGS(ev) &= ~PE_SUSPEND)
117 
118 #define WaPERLCB(ev)		(WaFLAGS(ev) & PE_PERLCB)
119 #define WaPERLCB_on(ev)		(WaFLAGS(ev) |= PE_PERLCB)
120 #define WaPERLCB_off(ev)	(WaFLAGS(ev) &= ~PE_PERLCB)
121 
122 #define WaTMPERLCB(ev)		(WaFLAGS(ev) & PE_TMPERLCB)
123 #define WaTMPERLCB_on(ev)	(WaFLAGS(ev) |= PE_TMPERLCB)
124 #define WaTMPERLCB_off(ev)	(WaFLAGS(ev) &= ~PE_TMPERLCB)
125 
126 /* RUNNOW should be event specific XXX */
127 #define WaRUNNOW(ev)		(WaFLAGS(ev) & PE_RUNNOW)
128 #define WaRUNNOW_on(ev)		(WaFLAGS(ev) |= PE_RUNNOW)
129 #define WaRUNNOW_off(ev)	(WaFLAGS(ev) &= ~PE_RUNNOW)
130 
131 #define WaCANCELLED(ev)		(WaFLAGS(ev) & PE_CANCELLED)
132 #define WaCANCELLED_on(ev)	(WaFLAGS(ev) |= PE_CANCELLED)
133 #define WaCANCELLED_off(ev)	(WaFLAGS(ev) &= ~PE_CANCELLED)
134 
135 #define WaDESTROYED(ev)		(WaFLAGS(ev) & PE_DESTROYED)
136 #define WaDESTROYED_on(ev)	(WaFLAGS(ev) |= PE_DESTROYED)
137 #define WaDESTROYED_off(ev)	(WaFLAGS(ev) &= ~PE_DESTROYED)
138 
139 #define WaCANDESTROY(ev)					\
140  (WaCANCELLED(ev) && ev->refcnt == 0 && !ev->mysv)
141 
142 
143 #define EvFLAGS(ev)		((pe_event*)ev)->flags
144 
145 #define EvPERLCB(ev)		(EvFLAGS(ev) & PE_PERLCB)
146 #define EvPERLCB_on(ev)		(EvFLAGS(ev) |= PE_PERLCB)
147 #define EvPERLCB_off(ev)	(EvFLAGS(ev) &= ~PE_PERLCB)
148