| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | static struct pe_watcher_vtbl pe_generic_vtbl; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 2 |  |  |  |  |  | static pe_watcher *pe_generic_allocate(HV *stash, SV *temple) { | 
| 4 |  |  |  |  |  |  | pe_generic *ev; | 
| 5 | 2 |  |  |  |  |  | EvNew(14, ev, 1, pe_generic); | 
| 6 | 2 |  |  |  |  |  | ev->base.vtbl = &pe_generic_vtbl; | 
| 7 | 2 |  |  |  |  |  | pe_watcher_init(&ev->base, stash, temple); | 
| 8 | 2 |  |  |  |  |  | ev->source = &PL_sv_undef; | 
| 9 | 2 |  |  |  |  |  | PE_RING_INIT(&ev->active, ev); | 
| 10 | 2 |  |  |  |  |  | WaREPEAT_on(ev); | 
| 11 | 2 |  |  |  |  |  | WaINVOKE1_off(ev); | 
| 12 | 2 |  |  |  |  |  | return (pe_watcher*) ev; | 
| 13 |  |  |  |  |  |  | } | 
| 14 |  |  |  |  |  |  |  | 
| 15 | 2 |  |  |  |  |  | static void pe_generic_dtor(pe_watcher *ev) { | 
| 16 | 2 |  |  |  |  |  | pe_generic *gw = (pe_generic *)ev; | 
| 17 | 2 |  |  |  |  |  | SvREFCNT_dec(gw->source); | 
| 18 | 2 |  |  |  |  |  | pe_watcher_dtor(ev); | 
| 19 | 2 |  |  |  |  |  | EvFree(14, ev); | 
| 20 | 2 |  |  |  |  |  | } | 
| 21 |  |  |  |  |  |  |  | 
| 22 | 2 |  |  |  |  |  | static char *pe_generic_start(pe_watcher *_ev, int repeat) { | 
| 23 | 2 |  |  |  |  |  | pe_generic *ev = (pe_generic*) _ev; | 
| 24 | 2 |  |  |  |  |  | SV *source = ev->source; | 
| 25 |  |  |  |  |  |  | pe_genericsrc *src; | 
| 26 | 2 | 50 |  |  |  |  | if (!_ev->callback) | 
| 27 | 0 |  |  |  |  |  | return "without callback"; | 
| 28 | 2 | 50 |  |  |  |  | if (!source || !SvOK(source)) | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 29 | 0 |  |  |  |  |  | return "without source"; | 
| 30 | 2 |  |  |  |  |  | src = sv_2genericsrc(source); | 
| 31 | 2 |  |  |  |  |  | PE_RING_UNSHIFT(&ev->active, &src->watchers); | 
| 32 | 2 |  |  |  |  |  | return 0; | 
| 33 |  |  |  |  |  |  | } | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 2 |  |  |  |  |  | static void pe_generic_stop(pe_watcher *_ev) { | 
| 36 | 2 |  |  |  |  |  | pe_generic *ev = (pe_generic*) _ev; | 
| 37 | 2 | 50 |  |  |  |  | PE_RING_DETACH(&ev->active); | 
| 38 | 2 |  |  |  |  |  | } | 
| 39 |  |  |  |  |  |  |  | 
| 40 | 6 |  |  |  |  |  | WKEYMETH(_generic_source) { | 
| 41 | 6 |  |  |  |  |  | pe_generic *gw = (pe_generic*)ev; | 
| 42 | 6 | 50 |  |  |  |  | if (nval) { | 
| 43 | 6 |  |  |  |  |  | SV *old = gw->source; | 
| 44 | 6 |  |  |  |  |  | int active = WaPOLLING(ev); | 
| 45 | 6 | 100 |  |  |  |  | if(SvOK(nval)) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 46 | 5 |  |  |  |  |  | (void) sv_2genericsrc(nval);  /* for type check */ | 
| 47 |  |  |  |  |  |  | } | 
| 48 | 3 | 50 |  |  |  |  | if (active) pe_watcher_off(ev); | 
| 49 | 3 |  |  |  |  |  | gw->source = SvREFCNT_inc(nval); | 
| 50 | 3 | 50 |  |  |  |  | if (active) pe_watcher_on(ev, 0); | 
| 51 | 3 |  |  |  |  |  | SvREFCNT_dec(old); | 
| 52 |  |  |  |  |  |  | } | 
| 53 |  |  |  |  |  |  | { | 
| 54 | 3 |  |  |  |  |  | dSP; | 
| 55 | 3 | 50 |  |  |  |  | XPUSHs(gw->source); | 
| 56 | 3 |  |  |  |  |  | PUTBACK; | 
| 57 |  |  |  |  |  |  | } | 
| 58 | 3 |  |  |  |  |  | } | 
| 59 |  |  |  |  |  |  |  | 
| 60 | 1 |  |  |  |  |  | static pe_genericsrc *pe_genericsrc_allocate(HV *stash, SV *temple) { | 
| 61 |  |  |  |  |  |  | pe_genericsrc *src; | 
| 62 | 1 |  |  |  |  |  | EvNew(16, src, 1, pe_genericsrc); | 
| 63 | 1 | 50 |  |  |  |  | src->mysv = stash || temple ? wrap_genericsrc(src, stash, temple) : 0; | 
|  |  | 0 |  |  |  |  |  | 
| 64 | 1 |  |  |  |  |  | PE_RING_INIT(&src->watchers, 0); | 
| 65 | 1 |  |  |  |  |  | return src; | 
| 66 |  |  |  |  |  |  | } | 
| 67 |  |  |  |  |  |  |  | 
| 68 | 1 |  |  |  |  |  | static void pe_genericsrc_dtor(pe_genericsrc *src) { | 
| 69 | 1 | 50 |  |  |  |  | PE_RING_DETACH(&src->watchers); | 
| 70 | 1 |  |  |  |  |  | EvFree(16, src); | 
| 71 | 1 |  |  |  |  |  | } | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | static HV *pe_genericsrc_stash; | 
| 74 |  |  |  |  |  |  |  | 
| 75 | 2 |  |  |  |  |  | static void pe_genericsrc_event(pe_genericsrc *src, SV *data) { | 
| 76 | 2 |  |  |  |  |  | pe_generic *wa = src->watchers.next->self; | 
| 77 | 5 | 100 |  |  |  |  | while(wa) { | 
| 78 | 3 |  |  |  |  |  | pe_datafulevent *ev = | 
| 79 | 3 |  |  |  |  |  | (pe_datafulevent*) (*wa->base.vtbl->new_event)(&wa->base); | 
| 80 | 3 |  |  |  |  |  | ++ev->base.hits; | 
| 81 | 3 |  |  |  |  |  | ev->data = SvREFCNT_inc(data); | 
| 82 | 3 |  |  |  |  |  | queueEvent(&ev->base); | 
| 83 | 3 |  |  |  |  |  | wa = wa->active.next->self; | 
| 84 |  |  |  |  |  |  | } | 
| 85 | 2 |  |  |  |  |  | } | 
| 86 |  |  |  |  |  |  |  | 
| 87 | 25 |  |  |  |  |  | static void boot_generic() { | 
| 88 | 25 |  |  |  |  |  | pe_watcher_vtbl *vt = &pe_generic_vtbl; | 
| 89 | 25 |  |  |  |  |  | memcpy(vt, &pe_watcher_base_vtbl, sizeof(pe_watcher_base_vtbl)); | 
| 90 | 25 |  |  |  |  |  | vt->dtor = pe_generic_dtor; | 
| 91 | 25 |  |  |  |  |  | vt->start = pe_generic_start; | 
| 92 | 25 |  |  |  |  |  | vt->stop = pe_generic_stop; | 
| 93 | 25 |  |  |  |  |  | pe_register_vtbl(vt, gv_stashpv("Event::generic",1), &datafulevent_vtbl); | 
| 94 | 25 |  |  |  |  |  | pe_genericsrc_stash = gv_stashpv("Event::generic::Source", 1); | 
| 95 | 25 |  |  |  |  |  | } |