1 /* -*- C -*- sometimes */
2 
3 #define MIN_PERL_DEFINE 1
4 
5 #ifdef __cplusplus
6 extern "C" {
7 #endif
8 
9 #include <EXTERN.h>
10 #include <perl.h>
11 #include <XSUB.h>
12 
13 #ifdef __cplusplus
14 }
15 #endif
16 
17 #include "ppport.h"
18 
19 /* lexical warnings -- waiting for appropriate magic from
20    paul.marquess@bt.com */
21 #if 0
22 static void Event_warn(const char* pat, ...) {
23     dTHX;
24     va_list args;
25     va_start(args, pat);
26     if (!ckWARN_d(WARN_ALL))
27 	return;
28     Perl_vwarner(aTHX_ WARN_ALL, pat, &args);
29     va_end(args);
30 }
31 
32 #  undef warn
33 #  define warn Event_warn
34 #endif
35 
36 #if 1
37 #ifdef warn
38 #  undef warn
39 #endif
40 #define warn Event_warn
41 
Event_warn(const char * pat,...)42 static void Event_warn(const char* pat, ...) {
43     STRLEN n_a;
44     dSP;
45     SV *msg;
46     va_list args;
47     /* perl_require_pv("Carp.pm");     Couldn't possibly be unloaded.*/
48     va_start(args, pat);
49     msg = sv_newmortal();
50     sv_vsetpvfn(msg, pat, strlen(pat), &args, Null(SV**), 0, 0);
51     va_end(args);
52     SvREADONLY_on(msg);
53     PUSHMARK(SP);
54     XPUSHs(msg);
55     PUTBACK;
56     perl_call_pv("Carp::carp", G_DISCARD);
57 }
58 #endif
59 
60 #ifdef croak
61 #  undef croak
62 #endif
63 #define croak Event_croak
64 
Event_croak(const char * pat,...)65 static void Event_croak(const char* pat, ...) {
66     STRLEN n_a;
67     dSP;
68     SV *msg;
69     va_list args;
70     /* perl_require_pv("Carp.pm");     Couldn't possibly be unloaded.*/
71     va_start(args, pat);
72     msg = sv_newmortal();
73     sv_vsetpvfn(msg, pat, strlen(pat), &args, Null(SV**), 0, 0);
74     va_end(args);
75     SvREADONLY_on(msg);
76     PUSHMARK(SP);
77     XPUSHs(msg);
78     PUTBACK;
79     perl_call_pv("Carp::croak", G_DISCARD);
80     PerlIO_puts(PerlIO_stderr(), "panic: Carp::croak failed\n");
81     (void)PerlIO_flush(PerlIO_stderr());
82     my_failure_exit();
83 }
84 
85 #ifdef WIN32
86 #   include <fcntl.h>
87 #endif
88 
89 #if defined(HAS_POLL)
90 # include <poll.h>
91 
92 /*
93 	Many operating systems claim to support poll yet they
94 	actually emulate it with select.  c/unix.c supports
95 	either poll or select but it doesn't know which one to
96 	use.  Here we try to detect if we have a native poll
97 	implementation.  If we do, we use it.  Otherwise,
98 	select is assumed.
99 */
100 
101 # ifndef POLLOUT
102 #  undef HAS_POLL
103 # endif
104 # ifndef POLLWRNORM
105 #  undef HAS_POLL
106 # endif
107 # ifndef POLLWRBAND
108 #  undef HAS_POLL
109 # endif
110 #endif
111 
112 /* Is time() portable everywhere?  Hope so!  XXX */
113 
fallback_NVtime()114 static NV fallback_NVtime()
115 { return time(0); }
116 
117 #include "Event.h"
118 
119 /* The following is for very simplistic memory leak detection. */
120 
121 #define MAX_MEMORYCOUNT 20
122 static int MemoryCount[MAX_MEMORYCOUNT];
dbg_count_memory(int id,int cnt)123 static void dbg_count_memory(int id, int cnt) {
124     assert(id >= 0 && id < MAX_MEMORYCOUNT);
125     MemoryCount[id] += cnt;
126 }
127 
128 #if EVENT_MEMORY_DEBUG
129 #  define EvNew(id, ptr, size, type) dbg_count_memory(id,1); New(0,ptr,size,type)
130 #  define EvFree(id, ptr) STMT_START { dbg_count_memory(id,-1); safefree(ptr); } STMT_END
131 #else
132 #  define EvNew(x, ptr, size, type) New(0,ptr,size,type)
133 #  define EvFree(id, ptr) safefree(ptr)
134 #endif
135 
136 static int LoopLevel, ExitLevel;
137 static int ActiveWatchers=0; /* includes WaACTIVE + queued events */
138 static int WarnCounter=16; /*XXX nuke */
139 static SV *DebugLevel;
140 static SV *Eval;
141 static pe_event_stats_vtbl Estat;
142 
143 /* IntervalEpsilon should be equal to the clock's sleep resolution
144    (poll or select) times two.  It probably needs to be bigger if you turn
145    on lots of debugging?  Can determine this dynamically? XXX */
146 static NV IntervalEpsilon = 0.0002;
147 static int TimeoutTooEarly=0;
148 
149 static struct EventAPI api;
150 #define NVtime() (*api.NVtime)()
151 
152 static int pe_sys_fileno(SV *sv, char *context);
153 
154 static void queueEvent(pe_event *ev);
155 static void dequeEvent(pe_event *ev);
156 
157 static void pe_watcher_cancel(pe_watcher *ev);
158 static void pe_watcher_suspend(pe_watcher *ev);
159 static void pe_watcher_resume(pe_watcher *ev);
160 static void pe_watcher_now(pe_watcher *ev);
161 static void pe_watcher_start(pe_watcher *ev, int repeat);
162 static void pe_watcher_stop(pe_watcher *ev, int cancel_events);
163 static char*pe_watcher_on(pe_watcher *wa, int repeat);
164 static void pe_watcher_off(pe_watcher *wa);
165 
166 /* The newHVhv in perl seems to mysteriously break in some cases.  Here
167    is a simple and safe (but maybe slow) implementation. */
168 
169 #ifdef newHVhv
170 # undef newHVhv
171 #endif
172 #define newHVhv event_newHVhv
173 
event_newHVhv(HV * ohv)174 static HV *event_newHVhv(HV *ohv) {
175     register HV *hv = newHV();
176     register HE *entry;
177     hv_iterinit(ohv);		/* NOTE: this resets the iterator */
178     while (entry = hv_iternext(ohv)) {
179 	hv_store(hv, HeKEY(entry), HeKLEN(entry),
180 		SvREFCNT_inc(HeVAL(entry)), HeHASH(entry));
181     }
182     return hv;
183 }
184 
pe_watcher_STORE_FALLBACK(pe_watcher * wa,SV * svkey,SV * nval)185 static void pe_watcher_STORE_FALLBACK(pe_watcher *wa, SV *svkey, SV *nval)
186 {
187     if (!wa->FALLBACK)
188 	wa->FALLBACK = newHV();
189     hv_store_ent(wa->FALLBACK, svkey, SvREFCNT_inc(nval), 0);
190 }
191 
192 /***************** STATS */
193 static int StatsInstalled=0;
pe_install_stats(pe_event_stats_vtbl * esvtbl)194 static void pe_install_stats(pe_event_stats_vtbl *esvtbl) {
195     ++StatsInstalled;
196     Copy(esvtbl, &Estat, 1, pe_event_stats_vtbl);
197     Estat.on=0;
198 }
pe_collect_stats(int yes)199 static void pe_collect_stats(int yes) {
200     if (!StatsInstalled)
201 	croak("collect_stats: no event statistics are available");
202     Estat.on = yes;
203 }
204 
205 #ifdef HAS_GETTIMEOFDAY
null_loops_per_second(int sec)206 NV null_loops_per_second(int sec)
207 {
208 	/*
209 	  This should be more realistic.  It is used to normalize
210 	  the benchmark against some theoretical perfect event loop.
211 	*/
212 	struct timeval start_tm, done_tm;
213 	NV elapse;
214 	unsigned count=0;
215 	int fds[2];
216 	if (pipe(fds) != 0) croak("pipe");
217 	gettimeofday(&start_tm, 0);
218 	do {
219 #ifdef HAS_POLL
220 	  struct pollfd map[2];
221 	  Zero(map, 2, struct pollfd);
222 	  map[0].fd = fds[0];
223 	  map[0].events = POLLIN | POLLOUT;
224 	  map[0].revents = 0;
225 	  map[1].fd = fds[1];
226 	  map[1].events = POLLIN | POLLOUT;
227 	  map[1].revents = 0;
228 	  poll(map, 2, 0);
229 #elif defined(HAS_SELECT)
230 	  struct timeval null;
231 	  fd_set rfds, wfds, efds;
232 	  FD_ZERO(&rfds);
233 	  FD_ZERO(&wfds);
234 	  FD_ZERO(&efds);
235 	  FD_SET(fds[0], &rfds);
236 	  FD_SET(fds[0], &wfds);
237 	  FD_SET(fds[1], &rfds);
238 	  FD_SET(fds[1], &wfds);
239 	  null.tv_sec = 0;
240 	  null.tv_usec = 0;
241 	  select(3,&rfds,&wfds,&efds,&null);
242 #else
243 #  error
244 #endif
245 	  ++count;
246 	  gettimeofday(&done_tm, 0);
247 	  elapse = (done_tm.tv_sec - start_tm.tv_sec +
248 		    (done_tm.tv_usec - start_tm.tv_usec) / 1000000);
249 	} while(elapse < sec);
250 	close(fds[0]);
251 	close(fds[1]);
252 return count/sec;
253 }
254 #else /* !HAS_GETTIMEOFDAY */
null_loops_per_second(int sec)255 NV null_loops_per_second(int sec)
256 { croak("sorry, gettimeofday is not available"); }
257 #endif
258 
259 
260 #include "typemap.c"
261 #include "timeable.c"
262 #include "hook.c"
263 #include "ev.c"
264 #include "watcher.c"
265 #include "idle.c"
266 #include "timer.c"
267 #include "io.c"
268 #include "unix.c"
269 #include "var.c"
270 #include "signal.c"
271 #include "tied.c"
272 #include "group.c"
273 #include "generic.c"
274 #include "queue.c"
275 
276 MODULE = Event		PACKAGE = Event
277 
278 PROTOTYPES: DISABLE
279 
280 BOOT:
281   LoopLevel = ExitLevel = 0;
282   DebugLevel = SvREFCNT_inc(perl_get_sv("Event::DebugLevel", 1));
283   Eval = SvREFCNT_inc(perl_get_sv("Event::Eval", 1));
284   Estat.on=0;
285   boot_timeable();
286   boot_hook();
287   boot_pe_event();
288   boot_pe_watcher();
289   boot_idle();
290   boot_timer();
291   boot_io();
292   boot_devpoll();
293   boot_var();
294   boot_tied();
295   boot_signal();
296   boot_group();
297   boot_generic();
298   boot_queue();
299   {
300       SV *apisv;
301       api.Ver = EventAPI_VERSION;
302       api.start = pe_watcher_start;
303       api.queue = queueEvent;
304       api.now = pe_watcher_now;
305       api.suspend = pe_watcher_suspend;
306       api.resume = pe_watcher_resume;
307       api.stop = pe_watcher_stop;
308       api.cancel = pe_watcher_cancel;
309       api.tstart = pe_timeable_start;
310       api.tstop  = pe_timeable_stop;
311       api.NVtime = fallback_NVtime;
312       api.new_idle =   (pe_idle*  (*)(HV*,SV*))    pe_idle_allocate;
313       api.new_timer =  (pe_timer* (*)(HV*,SV*))    pe_timer_allocate;
314       api.new_io =     (pe_io*    (*)(HV*,SV*))    pe_io_allocate;
315       api.new_var =    (pe_var*   (*)(HV*,SV*))    pe_var_allocate;
316       api.new_signal = (pe_signal*(*)(HV*,SV*))    pe_signal_allocate;
317       api.add_hook = capi_add_hook;
318       api.cancel_hook = pe_cancel_hook;
319       api.install_stats = pe_install_stats;
320       api.collect_stats = pe_collect_stats;
321       api.AllWatchers = &AllWatchers;
322       api.watcher_2sv = watcher_2sv;
323       api.sv_2watcher = sv_2watcher;
324       api.event_2sv = event_2sv;
325       api.sv_2event = sv_2event;
326       api.unloop = pe_unloop;
327       api.unloop_all = pe_unloop_all;
328       api.sv_2interval = sv_2interval;
329       api.events_mask_2sv = events_mask_2sv;
330       api.sv_2events_mask = sv_2events_mask;
331 
332       apisv = perl_get_sv("Event::API", 1);
333       sv_setiv(apisv, (IV)&api);
334       SvREADONLY_on(apisv);
335   }
336 
337 void
338 _add_hook(type, code)
339 	char *type
340 	SV *code
341 	CODE:
342 	pe_add_hook(type, 1, code, 0);
343 	/* would be nice to return new pe_qcallback* XXX */
344 
345 int
346 _timeout_too_early()
347 	CODE:
348 	RETVAL = TimeoutTooEarly;
349 	TimeoutTooEarly=0;
350 	OUTPUT:
351 	RETVAL
352 
353 void
_memory_counters()354 _memory_counters()
355      PPCODE:
356 {
357 #ifdef EVENT_MEMORY_DEBUG
358     int xx;
359     for (xx=0; xx < MAX_MEMORYCOUNT; xx++)
360 	XPUSHs(sv_2mortal(newSViv(MemoryCount[xx])));
361 #endif
362 }
363 
364 void
365 _incr_looplevel()
366      PPCODE:
367      ++LoopLevel;
368      ++ExitLevel;
369 
370 void
371 _decr_looplevel()
372      PPCODE:
373      --LoopLevel;
374 
375 void
376 unloop(...)
377      CODE:
378      pe_unloop(items? ST(0) : &PL_sv_undef);
379 
380 void
381 unloop_all(...)
382      CODE:
383      pe_unloop_all(items? ST(0) : &PL_sv_undef);
384 
385 bool
386 cache_time_api()
387 	CODE:
388 	SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
389 	if (!svp || !*svp || !SvIOK(*svp))
390 	    XSRETURN_NO;
391 	api.NVtime = INT2PTR(NV(*)(), SvIV(*svp));
392 	XSRETURN_YES;
393 
394 NV
395 time()
396 	PROTOTYPE:
397 	CODE:
398 	RETVAL = NVtime();
399 	OUTPUT:
400 	RETVAL
401 
402 void
403 sleep(tm)
404 	NV tm;
405 	PROTOTYPE: $
406 	CODE:
407 	pe_sys_sleep(tm);
408 
409 NV
410 null_loops_per_second(sec)
411 	int sec
412 
413 void
414 all_watchers()
415 	PROTOTYPE:
416 	PPCODE:
417 	pe_watcher *ev;
418 	if (!AllWatchers.next)
419 	  return;
420 	ev = (pe_watcher*) AllWatchers.next->self;
421 	while (ev) {
422 	  XPUSHs(watcher_2sv(ev));
423 	  ev = (pe_watcher*) ev->all.next->self;
424 	}
425 
426 void
427 all_idle()
428 	PROTOTYPE:
429 	PPCODE:
430 	pe_watcher *ev;
431 	if (!Idle.prev)
432 	  return;
433 	ev = (pe_watcher*) Idle.prev->self;
434 	while (ev) {
435 	  XPUSHs(watcher_2sv(ev));
436 	  ev = (pe_watcher*) ((pe_idle*)ev)->iring.prev->self;
437 	}
438 
439 void
440 all_running()
441 	PROTOTYPE:
442 	PPCODE:
443 	int fx;
444 	for (fx = CurCBFrame; fx >= 0; fx--) {
445 	  pe_watcher *ev = (CBFrame + fx)->ev->up; /* XXX */
446 	  XPUSHs(watcher_2sv(ev));
447 	  if (GIMME_V != G_ARRAY)
448 	    break;
449 	}
450 
451 void
452 queue(...)
453 	PROTOTYPE: $;$
454 	PREINIT:
455 	pe_watcher *wa;
456 	pe_event *ev;
457 	PPCODE:
458 	wa = (pe_watcher*) sv_2watcher(ST(0));
459 	if (items == 1) {
460 	    ev = (*wa->vtbl->new_event)(wa);
461 	    ++ev->hits;
462 	}
463 	else if (items == 2) {
464 	  if (SvNIOK(ST(1))) {
465 	    ev = (*wa->vtbl->new_event)(wa);
466 	    ev->hits += SvIV(ST(1));
467 	  }
468 	  else {
469 	    ev = (pe_event*) sv_2event(ST(1));
470 	    if (ev->up != wa)
471 	      croak("queue: event doesn't match watcher");
472 	  }
473 	}
474 	queueEvent(ev);
475 
476 int
477 one_event(...)
478 	PROTOTYPE: ;$
479 	CODE:
480 	NV maxtm = 60;
481 	if (items == 1) maxtm = SvNV(ST(0));
482 	RETVAL = safe_one_event(maxtm);
483 	OUTPUT:
484 	RETVAL
485 
486 void
487 _loop()
488 	CODE:
489 	pe_check_recovery();
490 	pe_reentry();
491         if (!ActiveWatchers)
492           warn("Event: loop without active watchers");
493 	while (ExitLevel >= LoopLevel && ActiveWatchers) {
494 	  ENTER;
495 	  SAVETMPS;
496 	  one_event(60);
497 	  FREETMPS;
498 	  LEAVE;
499 	}
500 	LEAVE; /* reentry */
501 
502 void
503 queue_pending()
504 	CODE:
505 	pe_queue_pending();
506 
507 int
508 _empty_queue(prio)
509 	int prio
510 	CODE:
511 	pe_check_recovery();
512 	pe_reentry();
513 	while (pe_empty_queue(prio));
514 	LEAVE; /* reentry */
515 
516 void
517 queue_time(prio)
518 	int prio
519 	PPCODE:
520 	NV max=0;
521 	int xx;
522 	if (prio < 0 || prio >= PE_QUEUES)
523 	  croak("queue_time(%d) out of domain [0..%d]",
524 		prio, PE_QUEUES-1);
525 	for (xx=0; xx <= prio; xx++)
526 	  if (max < QueueTime[xx]) max = QueueTime[xx];
527 	XPUSHs(max? sv_2mortal(newSVnv(max)) : &PL_sv_undef);
528 
529 
530 MODULE = Event		PACKAGE = Event::Event::Io
531 
532 void
533 pe_event::got()
534 	PPCODE:
535 	XPUSHs(sv_2mortal(events_mask_2sv(((pe_ioevent*)THIS)->got)));
536 
537 MODULE = Event		PACKAGE = Event::Event::Dataful
538 
539 void
540 pe_event::data()
541 	PPCODE:
542 	XPUSHs(((pe_datafulevent*)THIS)->data);
543 
544 MODULE = Event		PACKAGE = Event::Event
545 
546 void
DESTROY(ref)547 DESTROY(ref)
548 	SV *ref;
549 	CODE:
550 {
551 	pe_event *THIS = (pe_event*) sv_2event(ref);
552 	if (WaDEBUGx(THIS) >= 3) {
553 	    STRLEN n_a;
554 	    warn("Event=0x%x '%s' DESTROY SV=0x%x",
555 		 THIS, SvPV(THIS->up->desc, n_a),
556 		 THIS->mysv? SvRV(THIS->mysv) : 0);
557 	}
558 	(*THIS->vtbl->dtor)(THIS);
559 }
560 
561 void
562 pe_event::mom()
563 	PPCODE:
564 	if (--WarnCounter >= 0) warn("'mom' renamed to 'w'");
565 	XPUSHs(watcher_2sv(THIS->up));
566 
567 void
568 pe_event::w()
569 	PPCODE:
570 	XPUSHs(watcher_2sv(THIS->up));
571 
572 void
573 pe_event::hits()
574 	PPCODE:
575 	XPUSHs(sv_2mortal(newSViv(THIS->hits)));
576 
577 void
578 pe_event::prio()
579 	PPCODE:
580 	XPUSHs(sv_2mortal(newSViv(THIS->prio)));
581 
582 MODULE = Event		PACKAGE = Event::Watcher
583 
584 void
DESTROY(ref)585 DESTROY(ref)
586 	SV *ref;
587 	CODE:
588 {
589 	pe_watcher *THIS = (pe_watcher*) sv_2watcher(ref);
590 	assert(THIS);
591 	if (THIS->mysv) {
592 	    THIS->mysv=0;
593 	    if (WaCANDESTROY(THIS)) /*mysv*/
594 		(*THIS->vtbl->dtor)(THIS);
595 	}
596 }
597 
598 void
pending()599 pe_watcher::pending()
600 	PPCODE:
601 {
602     if (GIMME_V == G_ARRAY) {
603 	pe_event *ev = (pe_event *) THIS->events.prev->self;
604 	while (ev) {
605 	    XPUSHs(event_2sv(ev));
606 	    ev = (pe_event*) ev->peer.prev->self;
607 	}
608     } else {
609 	XPUSHs(THIS->events.next->self? &PL_sv_yes : &PL_sv_no);
610     }
611 }
612 
613 void
614 pe_watcher::again()
615 	CODE:
616 	pe_watcher_start(THIS, 1);
617 
618 void
619 pe_watcher::start()
620 	CODE:
621 	pe_watcher_start(THIS, 0);
622 
623 void
624 pe_watcher::suspend(...)
625 	CODE:
626 	if (items == 2) {
627 	    if (sv_true(ST(1)))
628 		pe_watcher_suspend(THIS);
629 	    else
630 		pe_watcher_resume(THIS);
631 	} else {
632 	    warn("Ambiguous use of suspend"); /*XXX*/
633 	    pe_watcher_suspend(THIS);
634 	    XSRETURN_YES;
635 	}
636 
637 void
638 pe_watcher::resume()
639 	CODE:
640 	warn("Please use $w->suspend(0) instead of resume"); /* DEPRECATED */
641 	pe_watcher_resume(THIS);
642 
643 void
644 pe_watcher::stop()
645 	CODE:
646 	pe_watcher_stop(THIS, 1);
647 
648 void
649 pe_watcher::cancel()
650 	CODE:
651 	pe_watcher_cancel(THIS);
652 
653 void
654 pe_watcher::now()
655 	CODE:
656 	pe_watcher_now(THIS);
657 
658 void
659 pe_watcher::use_keys(...)
660 	PREINIT:
661 	PPCODE:
662 	warn("use_keys is deprecated");
663 
664 void
665 pe_watcher::is_running(...)
666 	PPCODE:
667 	XPUSHs(sv_2mortal(newSViv(THIS->running)));
668 
669 void
670 pe_watcher::is_active(...)
671 	PPCODE:
672 	PUTBACK;
673 	XPUSHs(boolSV(WaACTIVE(THIS)));
674 
675 void
676 pe_watcher::is_suspended(...)
677 	PPCODE:
678 	PUTBACK;
679 	XPUSHs(boolSV(WaSUSPEND(THIS)));
680 
681 void
682 pe_watcher::is_cancelled(...)
683 	PPCODE:
684 	PUTBACK;
685 	XPUSHs(boolSV(WaCANCELLED(THIS)));
686 
687 void
688 pe_watcher::cb(...)
689 	PPCODE:
690 	PUTBACK;
691 	_watcher_callback(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
692 	SPAGAIN;
693 
694 void
695 pe_watcher::cbtime(...)
696 	PPCODE:
697 	PUTBACK;
698 	_watcher_cbtime(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
699 	SPAGAIN;
700 
701 void
702 pe_watcher::desc(...)
703 	PPCODE:
704 	PUTBACK;
705 	_watcher_desc(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
706 	SPAGAIN;
707 
708 void
709 pe_watcher::debug(...)
710 	PPCODE:
711 	PUTBACK;
712 	_watcher_debug(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
713 	SPAGAIN;
714 
715 void
716 pe_watcher::prio(...)
717 	PPCODE:
718 	PUTBACK;
719 	_watcher_priority(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
720 	SPAGAIN;
721 
722 void
723 pe_watcher::reentrant(...)
724 	PPCODE:
725 	PUTBACK;
726 	_watcher_reentrant(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
727 	SPAGAIN;
728 
729 void
730 pe_watcher::repeat(...)
731 	PPCODE:
732 	PUTBACK;
733 	_watcher_repeat(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
734 	SPAGAIN;
735 
736 void
737 pe_watcher::max_cb_tm(...)
738 	PPCODE:
739 	PUTBACK;
740 	_watcher_max_cb_tm(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
741 	SPAGAIN;
742 
743 MODULE = Event		PACKAGE = Event::Watcher::Tied
744 
745 void
746 allocate(clname, temple)
747 	SV *clname
748 	SV *temple
749 	PPCODE:
750 	if (!SvROK(temple)) croak("Bad template");
751 	XPUSHs(watcher_2sv(pe_tied_allocate(gv_stashsv(clname, 1),
752 					    SvRV(temple))));
753 
754 void
755 pe_watcher::hard(...)
756 	PPCODE:
757 	PUTBACK;
758 	_timeable_hard(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
759 	SPAGAIN;
760 
761 void
762 pe_watcher::at(...)
763 	PPCODE:
764 	PUTBACK;
765 	_tied_at(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
766 	SPAGAIN;
767 
768 void
769 pe_watcher::flags(...)
770 	PPCODE:
771 	PUTBACK;
772 	_tied_flags(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
773 	SPAGAIN;
774 
775 MODULE = Event		PACKAGE = Event::idle
776 
777 void
778 allocate(clname, temple)
779 	SV *clname;
780 	SV *temple;
781 	PPCODE:
782 	if (!SvROK(temple)) croak("Bad template");
783 	XPUSHs(watcher_2sv(pe_idle_allocate(gv_stashsv(clname, 1),
784 			SvRV(temple))));
785 
786 void
787 pe_watcher::hard(...)
788 	PPCODE:
789 	PUTBACK;
790 	_timeable_hard(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
791 	SPAGAIN;
792 
793 void
794 pe_watcher::max(...)
795 	PPCODE:
796 	PUTBACK;
797 	_idle_max_interval(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
798 	SPAGAIN;
799 
800 void
801 pe_watcher::min(...)
802 	PPCODE:
803 	PUTBACK;
804 	_idle_min_interval(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
805 	SPAGAIN;
806 
807 MODULE = Event		PACKAGE = Event::timer
808 
809 void
810 allocate(clname, temple)
811 	SV *clname;
812 	SV *temple;
813 	PPCODE:
814 	XPUSHs(watcher_2sv(pe_timer_allocate(gv_stashsv(clname, 1),
815 			SvRV(temple))));
816 
817 void
818 pe_watcher::at(...)
819 	PPCODE:
820 	PUTBACK;
821 	_timer_at(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
822 	SPAGAIN;
823 
824 void
825 pe_watcher::hard(...)
826 	PPCODE:
827 	PUTBACK;
828 	_timeable_hard(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
829 	SPAGAIN;
830 
831 void
832 pe_watcher::interval(...)
833 	PPCODE:
834 	PUTBACK;
835 	_timer_interval(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
836 	SPAGAIN;
837 
838 MODULE = Event		PACKAGE = Event::io
839 
840 void
841 allocate(clname, temple)
842 	SV *clname;
843 	SV *temple;
844 	PPCODE:
845 	if (!SvROK(temple)) croak("Bad template");
846 	XPUSHs(watcher_2sv(pe_io_allocate(gv_stashsv(clname, 1),
847 			SvRV(temple))));
848 
849 void
850 pe_watcher::poll(...)
851 	PPCODE:
852 	PUTBACK;
853 	_io_poll(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
854 	SPAGAIN;
855 
856 void
857 pe_watcher::fd(...)
858 	PPCODE:
859 	PUTBACK;
860 	_io_handle(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
861 	SPAGAIN;
862 
863 void
864 pe_watcher::timeout(...)
865 	PPCODE:
866 	PUTBACK;
867 	_io_timeout(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
868 	SPAGAIN;
869 
870 void
871 pe_watcher::timeout_cb(...)
872 	PPCODE:
873 	PUTBACK;
874 	_io_timeout_cb(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
875 	SPAGAIN;
876 
877 MODULE = Event		PACKAGE = Event::var
878 
879 void
880 allocate(clname, temple)
881 	SV *clname;
882 	SV *temple;
883 	PPCODE:
884 	XPUSHs(watcher_2sv(pe_var_allocate(gv_stashsv(clname, 1),
885 		SvRV(temple))));
886 
887 void
888 pe_watcher::var(...)
889 	PPCODE:
890 	PUTBACK;
891 	_var_variable(THIS, items == 2? ST(1) : 0); /* don't mortalcopy!! */
892 	SPAGAIN;
893 
894 void
895 pe_watcher::poll(...)
896 	PPCODE:
897 	PUTBACK;
898 	_var_events(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
899 	SPAGAIN;
900 
901 MODULE = Event		PACKAGE = Event::signal
902 
903 void
904 allocate(clname, temple)
905 	SV *clname;
906 	SV *temple;
907 	PPCODE:
908 	XPUSHs(watcher_2sv(pe_signal_allocate(gv_stashsv(clname, 1),
909 		SvRV(temple))));
910 
911 void
912 pe_watcher::signal(...)
913 	PPCODE:
914 	PUTBACK;
915 	_signal_signal(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
916 	SPAGAIN;
917 
918 MODULE = Event		PACKAGE = Event::group
919 
920 void
921 allocate(clname, temple)
922      SV *clname;
923      SV *temple;
924      PPCODE:
925      XPUSHs(watcher_2sv(pe_group_allocate(gv_stashsv(clname, 1),
926 		SvRV(temple))));
927 
928 void
929 pe_watcher::timeout(...)
930 	PPCODE:
931 	PUTBACK;
932 	_group_timeout(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
933 	SPAGAIN;
934 
935 void
936 pe_watcher::add(...)
937 	PPCODE:
938 	PUTBACK;
939 	_group_add(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
940 	SPAGAIN;
941 
942 void
943 pe_watcher::del(...)
944 	PPCODE:
945 	PUTBACK;
946 	_group_del(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
947 	SPAGAIN;
948 
949 MODULE = Event		PACKAGE = Event::generic
950 
951 void
952 allocate(clname, temple)
953      SV *clname;
954      SV *temple;
955      PPCODE:
956      XPUSHs(watcher_2sv(pe_generic_allocate(gv_stashsv(clname, 1),
957 		SvRV(temple))));
958 
959 void
960 pe_watcher::source(...)
961 	PPCODE:
962 	PUTBACK;
963 	_generic_source(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
964 	SPAGAIN;
965 
966 MODULE = Event		PACKAGE = Event::generic::Source
967 
968 void
969 allocate(clname, temple)
970 	SV *clname;
971 	SV *temple;
972 	PPCODE:
973 	if (!SvROK(temple)) croak("Bad template");
974 	XPUSHs(genericsrc_2sv(pe_genericsrc_allocate(gv_stashsv(clname, 1),
975 			SvRV(temple))));
976 
977 void
DESTROY(ref)978 DESTROY(ref)
979 	SV *ref;
980 	CODE:
981 {
982 	pe_genericsrc_dtor(sv_2genericsrc(ref));
983 }
984 
985 void
986 pe_genericsrc::event(...)
987 	PPCODE:
988 	pe_genericsrc_event(THIS,
989 		items >= 2 ? sv_mortalcopy(ST(1)) : &PL_sv_undef);
990