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