#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)