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