Does everyone still think that group watchers are a good idea?  If so,
show me some demo scripts!  ;-)

----- Forwarded message from [EMAIL PROTECTED] -----

Date: Mon, 7 Feb 2000 22:34:11 +0100
Subject: CPAN Upload: JPRIT/Event-0.65.tar.gz
From: [EMAIL PROTECTED]
To: [EMAIL PROTECTED],
    [EMAIL PROTECTED]

The uploaded file

    Event-0.65.tar.gz

has entered CPAN as

  file: $CPAN/authors/id/JPRIT/Event-0.65.tar.gz
  size: 64725 bytes
   md5: 4eaeb58978f3379e4d404a3deaff49d4

No action is required on your part
Request entered by: JPRIT (Joshua N. Pritikin)
Request entered on: Mon, 07 Feb 2000 21:33:05 GMT
Request completed:  Mon, 07 Feb 2000 21:34:11 GMT

        Virtually Yours,
        Id: paused,v 1.68 1999/10/22 14:39:12 k Exp k 


----- End forwarded message -----

# This is a patch for Event-0.64 to update it to Event-0.65
# 
# To apply this patch:
# STEP 1: Chdir to the source directory.
# STEP 2: Run the 'applypatch' program with this patch file as input.
#
# If you do not have 'applypatch', it is part of the 'makepatch' package
# that you can fetch from the Comprehensive Perl Archive Network:
# http://www.perl.com/CPAN/authors/Johan_Vromans/makepatch-x.y.tar.gz
# In the above URL, 'x' should be 2 or higher.
#
# To apply this patch without the use of 'applypatch':
# STEP 1: Chdir to the source directory.
# If you have a decent Bourne-type shell:
# STEP 2: Run the shell with this file as input.
# If you don't have such a shell, you may need to manually create
# the files as shown below.
# STEP 3: Run the 'patch' program with this file as input.
#
# These are the commands needed to create/delete files/directories:
#
touch 'c/group.c'
chmod 0444 'c/group.c'
touch 'demo/group.t'
chmod 0444 'demo/group.t'
touch 'lib/Event/group.pm'
chmod 0444 'lib/Event/group.pm'
touch 't/fifo.t'
chmod 0444 't/fifo.t'
#
# This command terminates the shell and need not be executed manually.
exit
#
#### End of Preamble ####

#### Patch data follows ####
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/ChangeLog' 
'/usr/tmp/mp4384.d/new/Event-0.65/ChangeLog'
Index: ./ChangeLog
--- ./ChangeLog Fri Feb  4 17:42:33 2000
+++ ./ChangeLog Mon Feb  7 16:21:58 2000
@@ -1,3 +1,16 @@
+2000-02-07  Joshua Pritikin  <[EMAIL PROTECTED]>
+
+       * Release 0.65.
+
+       * Group watchers for watching watchers.  See demo/group.t
+
+       * Fix got() documentation, spotted by
+       [EMAIL PROTECTED]
+
+       * Make callback a prerequisite for starting watchers.
+
+       * Add test checking FIFO dispatch of equal priority events.
+
 2000-02-04  Joshua Pritikin  <[EMAIL PROTECTED]>
 
        * Release 0.64.
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/Event.h' 
'/usr/tmp/mp4384.d/new/Event-0.65/Event.h'
Index: ./Event.h
--- ./Event.h   Tue Feb  1 12:18:39 2000
+++ ./Event.h   Mon Feb  7 15:19:18 2000
@@ -150,7 +150,7 @@ struct pe_watcher_vtbl {
 #define WaDESTROYED_off(ev)    (WaFLAGS(ev) &= ~PE_DESTROYED)
 
 #define WaCANDESTROY(ev)                                       \
- (WaCANCELLED(ev) && ev->event_counter == 0 && !ev->mysv)
+ (WaCANCELLED(ev) && ev->refcnt == 0 && !ev->mysv)
 
 
 #define EvFLAGS(ev)            ((pe_event*)ev)->flags
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/Event.xs' 
'/usr/tmp/mp4384.d/new/Event-0.65/Event.xs'
Index: ./Event.xs
--- ./Event.xs  Fri Feb  4 17:39:18 2000
+++ ./Event.xs  Mon Feb  7 15:16:44 2000
@@ -236,6 +236,7 @@ double null_loops_per_second(int sec)
 #include "var.c"
 #include "signal.c"
 #include "tied.c"
+#include "group.c"
 #include "queue.c"
 
 MODULE = Event         PACKAGE = Event
@@ -256,6 +257,7 @@ BOOT:
   boot_var();
   boot_tied();
   boot_signal();
+  boot_group();
   boot_queue();
   {
       struct EventAPI *api;
@@ -534,7 +536,14 @@ DESTROY(ref)
 int
 pe_watcher::pending()
        CODE:
-       RETVAL = THIS->event_counter;
+{
+    pe_ring *lk = &THIS->events;
+    RETVAL = 0;
+    while (lk->next->self) {  /* should not be too wasteful */
+       ++RETVAL;
+       lk = lk->next;
+    }
+}
        OUTPUT:
        RETVAL
 
@@ -857,4 +866,35 @@ pe_watcher::signal(...)
        PPCODE:
        PUTBACK;
        _signal_signal(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
+       SPAGAIN;
+
+MODULE = Event         PACKAGE = Event::group
+
+void
+allocate(clname, temple)
+     SV *clname;
+     SV *temple;
+     PPCODE:
+     XPUSHs(watcher_2sv(pe_group_allocate(gv_stashsv(clname, 1),
+               SvRV(temple))));
+
+void
+pe_watcher::timeout(...)
+       PPCODE:
+       PUTBACK;
+       _group_timeout(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
+       SPAGAIN;
+
+void
+pe_watcher::add(...)
+       PPCODE:
+       PUTBACK;
+       _group_add(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
+       SPAGAIN;
+
+void
+pe_watcher::del(...)
+       PPCODE:
+       PUTBACK;
+       _group_del(THIS, items == 2? sv_mortalcopy(ST(1)) : 0);
        SPAGAIN;
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/MANIFEST' 
'/usr/tmp/mp4384.d/new/Event-0.65/MANIFEST'
Index: ./MANIFEST
--- ./MANIFEST  Thu Feb  3 16:36:05 2000
+++ ./MANIFEST  Mon Feb  7 16:21:03 2000
@@ -9,6 +9,7 @@ Makefile.PL
 README
 TODO
 c/ev.c
+c/group.c
 c/hook.c
 c/idle.c
 c/io.c
@@ -23,6 +24,7 @@ c/var.c
 c/watcher.c
 demo/in.pl
 demo/inactivity.t
+demo/group.t
 demo/process.pm
 demo/readline.t
 demo/spin_io.t
@@ -32,6 +34,7 @@ lib/Event.pod
 lib/Event/EventAPI.h
 lib/Event/MakeMaker.pm
 lib/Event/Watcher.pm
+lib/Event/group.pm
 lib/Event/idle.pm
 lib/Event/inactivity.pm
 lib/Event/io.pm
@@ -47,6 +50,7 @@ t/bored.t
 t/callback.t
 t/delete.t
 t/eval.t
+t/fifo.t
 t/hook.t
 t/hup.t
 t/idle.t
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/TODO' 
'/usr/tmp/mp4384.d/new/Event-0.65/TODO'
Index: ./TODO
--- ./TODO      Thu Feb  3 16:32:58 2000
+++ ./TODO      Mon Feb  7 16:29:35 2000
@@ -1,10 +1,11 @@
+deprecate inactivity completely?
+
+add timeout for var watchers?
+
 increase the number of priority levels?
   ASYNC    0    1    2    3    4    5    6    7    8    9   IDLE
                          HIGH           NORM
 
-rethink
-  pe_check_recovery & ENTER/LEAVE points
-
 find owner for Win32 port
 
 documentation
@@ -18,13 +19,8 @@ optimization
     queue events from both sides?
   try to hoist system calls from the inner loop
 
-inactivity
-  For a single watcher, a simple timeout would surely have the same
-  effect. But if there would be a watcher grouping feature (as you
-  indicated), watching groups of watchers could provide a new dimension
-  of flexibility.
-
-add timeout for var watchers?
+rethink
+  pe_check_recovery & ENTER/LEAVE points
 
 [EMAIL PROTECTED] signal discussion:
   The API rsignal overrides the current signal handler.  If the signal
@@ -39,9 +35,6 @@ there seems to be some sort of bug in th
 > Use of uninitialized value during global destruction.
 > Explicit blessing to '' (assuming package main) during global
 > destruction.
-
-If I install a watcher and delay the call of loop(), what about
-events arriving in the meantime?
 
 loop
   StarvePrio?
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/c/ev.c' 
'/usr/tmp/mp4384.d/new/Event-0.65/c/ev.c'
Index: ./c/ev.c
--- ./c/ev.c    Thu Feb  3 08:48:26 2000
+++ ./c/ev.c    Mon Feb  7 13:26:55 2000
@@ -11,7 +11,7 @@ pe_event_vtbl event_vtbl, ioevent_vtbl;
 static void pe_anyevent_init(pe_event *ev, pe_watcher *wa) {
     assert(wa);
     ev->up = wa;
-    ++wa->event_counter;
+    ++wa->refcnt;
     ev->mysv = 0;
     PE_RING_INIT(&ev->peer, ev);
     PE_RING_UNSHIFT(&ev->peer, &wa->events);
@@ -36,7 +36,7 @@ static void pe_anyevent_dtor(pe_event *e
     ev->callback = 0;
     PE_RING_DETACH(&ev->peer);
     PE_RING_DETACH(&ev->que);
-    --wa->event_counter;
+    --wa->refcnt;
     if (WaCANDESTROY(wa)) /* running */
        (*wa->vtbl->dtor)(wa);
 }
gdiff -up /dev/null '/usr/tmp/mp4384.d/new/Event-0.65/c/group.c'
Index: ./c/group.c
--- ./c/group.c Wed Dec 31 19:00:00 1969
+++ ./c/group.c Mon Feb  7 16:17:11 2000
@@ -0,0 +1,153 @@
+static struct pe_watcher_vtbl pe_group_vtbl;
+
+static pe_watcher *pe_group_allocate(HV *stash, SV *temple) {
+    pe_group *ev;
+    EvNew(12, ev, 1, pe_group);
+    ev->base.vtbl = &pe_group_vtbl;
+    PE_RING_INIT(&ev->tm.ring, ev);
+    ev->tm.at = 0;
+    ev->timeout = &PL_sv_undef;
+    ev->members = 3;
+    EvNew(13, ev->member, ev->members, pe_watcher*);
+    Zero(ev->member, ev->members, pe_watcher*);
+    pe_watcher_init(&ev->base, stash, temple);
+    WaREPEAT_on(ev);
+    return (pe_watcher*) ev;
+}
+
+static void pe_group_dtor(pe_watcher *ev) {
+    int xx;
+    pe_group *gp = (pe_group*) ev;
+    SvREFCNT_dec(gp->timeout);
+    for (xx=0; xx < gp->members; xx++) {
+       pe_watcher *mb = gp->member[xx];
+       if (mb)
+           --mb->refcnt;
+    }
+    EvFree(13, gp->member);
+    pe_watcher_dtor(ev);
+    EvFree(12, ev);
+}
+
+static char *pe_group_start(pe_watcher *ev, int repeat) {
+    pe_group *gp = (pe_group*) ev;
+    double timeout;
+
+    if (!ev->callback)
+       return "without callback";
+    if (!sv_2interval(gp->timeout, &timeout))
+       return "repeating group has no timeout";
+
+    gp->since = WaHARD(ev)? gp->tm.at : NVtime();
+    gp->tm.at = timeout + gp->since;
+    pe_timeable_start(&gp->tm);
+    return 0;
+}
+
+static void pe_group_stop(pe_watcher *ev)
+{ pe_timeable_stop(&((pe_group*)ev)->tm); }
+
+static void pe_group_alarm(pe_watcher *wa, pe_timeable *tm) {
+    STRLEN n_a;
+    pe_group *gp = (pe_group*) wa;
+    double timeout;
+    double remaining;
+    double now = NVtime();
+    int xx;
+    for (xx=0; xx < gp->members; xx++) {
+       pe_watcher *mb = gp->member[xx];
+       if (!mb) continue;
+       if (gp->since < mb->cbtime) {
+           gp->since = mb->cbtime;
+       }
+    }
+
+    if (!sv_2interval(gp->timeout, &timeout))
+       croak("Event: can't extract timeout"); /* impossible */
+
+    remaining = gp->since + timeout - now;
+    if (remaining > IntervalEpsilon) {
+       gp->tm.at = now + remaining;
+       pe_timeable_start(&gp->tm);
+    } else {
+       pe_event *ev = (*wa->vtbl->new_event)(wa);
+       ++ev->hits;
+       queueEvent(ev);
+    }
+}
+
+/* publish C API XXX */
+static void pe_group_add(pe_group *gp, pe_watcher *wa) {
+    int ok=0;
+    int xx;
+    if (gp == (pe_group*) wa) {
+       STRLEN n_a;
+       croak("Event: can't add group '%s' to itself",
+             SvPV(gp->base.desc, n_a));
+    }
+    ++wa->refcnt;
+    for (xx=0; xx < gp->members; xx++) {
+       if (!gp->member[xx]) {
+           gp->member[xx] = wa;
+           ok=1; break;
+       }
+    }
+    if (!ok) {  /* expand array */
+       pe_watcher **ary;
+       EvNew(13, ary, gp->members*2, pe_watcher*);
+       Copy(gp->member, ary, gp->members, sizeof(pe_watcher*));
+       EvFree(13, gp->member);
+       gp->member = ary;
+       gp->member[gp->members] = wa;
+       gp->members *= 2;
+    }
+}
+
+static void pe_group_del(pe_group *gp, pe_watcher *target) {
+    int xx;
+    for (xx=0; xx < gp->members; xx++) {
+       if (gp->member[xx] != target)
+           continue;
+       --target->refcnt;
+       gp->member[xx] = 0;
+       break;
+    }
+}
+
+WKEYMETH(_group_timeout) {
+    pe_group *gp = (pe_group*)ev;
+    if (!nval) {
+       dSP;
+       XPUSHs(gp->timeout);
+       PUTBACK;
+    } else {
+       SV *old = gp->timeout;
+       gp->timeout = SvREFCNT_inc(nval);
+       SvREFCNT_dec(old);
+       /* recalc expiration XXX */
+    }
+}
+
+WKEYMETH(_group_add) {
+    pe_group *gp = (pe_group*)ev;
+    if (!nval)
+       return;
+    pe_group_add(gp, sv_2watcher(nval));
+}
+
+WKEYMETH(_group_del) {
+    pe_group *gp = (pe_group*)ev;
+    if (!nval)
+       return;
+    pe_group_del(gp, sv_2watcher(nval));
+}
+
+static void boot_group() {
+    pe_watcher_vtbl *vt = &pe_group_vtbl;
+    memcpy(vt, &pe_watcher_base_vtbl, sizeof(pe_watcher_base_vtbl));
+    vt->dtor = pe_group_dtor;
+    vt->start = pe_group_start;
+    vt->stop = pe_group_stop;
+    vt->alarm = pe_group_alarm;
+    pe_register_vtbl(vt, gv_stashpv("Event::group",1), &event_vtbl);
+}
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/c/idle.c' 
'/usr/tmp/mp4384.d/new/Event-0.65/c/idle.c'
Index: ./c/idle.c
--- ./c/idle.c  Tue Feb  1 12:26:44 2000
+++ ./c/idle.c  Mon Feb  7 10:15:08 2000
@@ -28,6 +28,8 @@ static char *pe_idle_start(pe_watcher *e
     double now;
     double min,max;
     pe_idle *ip = (pe_idle*) ev;
+    if (!ev->callback)
+       return "without callback";
     if (SvOK(ip->min_interval) || SvOK(ip->max_interval))
        WaCBTIME_on(ev);
     else
@@ -48,7 +50,7 @@ static char *pe_idle_start(pe_watcher *e
            pe_timeable_start(&ip->tm);
        }
     }
-    return 0; /* always succeeds */
+    return 0;
 }
 
 static void pe_idle_alarm(pe_watcher *wa, pe_timeable *_ignore) {
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/c/io.c' 
'/usr/tmp/mp4384.d/new/Event-0.65/c/io.c'
Index: ./c/io.c
--- ./c/io.c    Tue Feb  1 12:33:58 2000
+++ ./c/io.c    Mon Feb  7 10:17:15 2000
@@ -44,12 +44,16 @@ static char *pe_io_start(pe_watcher *_ev
        officially supported but maybe it is too unix specific. */
 
     if (ev->fd >= 0) {
+       if (!ev->base.callback)
+           return "Without io callback";
        PE_RING_UNSHIFT(&ev->ioring, &IOWatch);
        ++IOWatchCount;
        IOWatch_OK = 0;
        ++ok;
     }
     if (ev->timeout) {
+       if (!ev->base.callback && !ev->tm_callback)
+           return "without timeout callback";
        WaCBTIME_on(ev);
        ev->poll |= PE_T;
        ev->tm.at = NVtime() + ev->timeout;  /* too early okay */
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/c/signal.c' 
'/usr/tmp/mp4384.d/new/Event-0.65/c/signal.c'
Index: ./c/signal.c
--- ./c/signal.c        Tue Feb  1 12:30:27 2000
+++ ./c/signal.c        Mon Feb  7 10:17:55 2000
@@ -49,8 +49,10 @@ static void pe_signal_dtor(pe_watcher *e
 static char *pe_signal_start(pe_watcher *_ev, int repeat) {
     pe_signal *ev = (pe_signal*) _ev;
     int sig = ev->signal;
+    if (!_ev->callback)
+       return "without callback";
     if (sig == 0)
-       return "no signal";
+       return "without signal";
     if (PE_RING_EMPTY(&Sigring[sig]))
        rsignal(sig, process_sighandler);
     PE_RING_UNSHIFT(&ev->sring, &Sigring[sig]);
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/c/timer.c' 
'/usr/tmp/mp4384.d/new/Event-0.65/c/timer.c'
Index: ./c/timer.c
--- ./c/timer.c Tue Feb  1 12:28:04 2000
+++ ./c/timer.c Mon Feb  7 13:24:54 2000
@@ -22,6 +22,8 @@ static void pe_timer_dtor(pe_watcher *ev
 static char *pe_timer_start(pe_watcher *ev, int repeat) {
     STRLEN n_a;
     pe_timer *tm = (pe_timer*) ev;
+    if (!ev->callback)
+       return "without callback";
     if (repeat) {
        /* We just finished the callback and need to re-insert at
           the appropriate time increment. */
@@ -29,8 +31,6 @@ static char *pe_timer_start(pe_watcher *
 
        if (!sv_2interval(tm->interval, &interval))
            return "repeating timer has no interval";
-       if (interval <= 0)
-           return "non-positive interval";
 
        tm->tm.at = interval + (WaHARD(ev)? tm->tm.at : NVtime());
     }
@@ -74,6 +74,7 @@ WKEYMETH(_timer_interval) {
        SV *old = tp->interval;
        tp->interval = SvREFCNT_inc(nval);
        SvREFCNT_dec(old);
+       /* recalc expiration XXX */
     }
 }
 
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/c/typemap.c' 
'/usr/tmp/mp4384.d/new/Event-0.65/c/typemap.c'
Index: ./c/typemap.c
--- ./c/typemap.c       Thu Jan 20 13:50:53 2000
+++ ./c/typemap.c       Mon Feb  7 13:25:24 2000
@@ -104,19 +104,20 @@ static int sv_2interval(SV *in, double *
        sv = SvRV(sv);
     if (SvNOK(sv)) {
        *out = SvNVX(sv);
-       return 1;
-    }
-    if (SvIOK(sv)) {
+    } else if (SvIOK(sv)) {
        *out = SvIVX(sv);
-       return 1;
-    }
-    if (looks_like_number(sv)) {
+    } else if (looks_like_number(sv)) {
        *out = SvNV(sv);
-       return 1;
+    } else {
+       sv_dump(in);
+       croak("Interval must be a number of reference to a number");
+       return 0;
+    }
+    if (*out < 0) {
+       warn("Event: negative timeout (%.2f) clipped to zero", *out);
+       *out = 0;
     }
-    sv_dump(in);
-    croak("Interval must be a number of reference to a number");
-    return 0;
+    return 1;
 }
 
 static SV* events_mask_2sv(int mask) {
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/c/var.c' 
'/usr/tmp/mp4384.d/new/Event-0.65/c/var.c'
Index: ./c/var.c
--- ./c/var.c   Thu Feb  3 16:09:09 2000
+++ ./c/var.c   Mon Feb  7 10:18:42 2000
@@ -60,10 +60,12 @@ static char *pe_var_start(pe_watcher *_e
     pe_var *ev = (pe_var*) _ev;
     SV *sv = ev->variable;
 
+    if (!_ev->callback)
+       return "without callback";
     if (!sv || !SvOK(sv))
        return "watching what?";
     if (!ev->events)
-       return "no poll events specified";
+       return "without poll events specified";
     sv = SvRV(sv);
     if (SvREADONLY(sv))
        return "cannot trace read-only variable";
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/c/watcher.c' 
'/usr/tmp/mp4384.d/new/Event-0.65/c/watcher.c'
Index: ./c/watcher.c
--- ./c/watcher.c       Tue Feb  1 12:31:51 2000
+++ ./c/watcher.c       Mon Feb  7 13:26:35 2000
@@ -34,7 +34,7 @@ static void pe_watcher_init(pe_watcher *
     WaREENTRANT_on(ev);
     ev->FALLBACK = 0;
     NextID = (NextID+1) & 0x7fff; /* make it look like the kernel :-, */
-    ev->event_counter = 0;
+    ev->refcnt = 0;
     ev->desc = newSVpvn("??",2);
     ev->running = 0;
     ev->max_cb_tm = 1;  /* make default configurable? */
gdiff -up /dev/null '/usr/tmp/mp4384.d/new/Event-0.65/demo/group.t'
Index: ./demo/group.t
--- ./demo/group.t      Wed Dec 31 19:00:00 1969
+++ ./demo/group.t      Mon Feb  7 16:20:44 2000
@@ -0,0 +1,25 @@
+#!./perl -w
+
+use strict;
+use Test; plan test => 6;
+use Event qw(time);
+require Event::group;
+
+my $g = Event->group(parked=>1, timeout => 1.95, cb => sub {
+                        my $e = shift;
+                        warn "timeout at ".$e->w->cbtime;
+                    },
+                    add => Event->timer(desc => '1', interval => 2,
+                                        cb => sub {
+                                            my $e = shift;
+                                            warn "boink #1 at ".$e->w->cbtime
+                                        }),
+                    add => Event->timer(desc => '2', interval => 2.5,
+                                        cb => sub {
+                                            my $e = shift;
+                                            warn "boink #2 at ".$e->w->cbtime
+                                        }),
+                   );
+$g->start;
+
+Event::loop();
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/lib/Event.pm' 
'/usr/tmp/mp4384.d/new/Event-0.65/lib/Event.pm'
Index: ./lib/Event.pm
--- ./lib/Event.pm      Fri Feb  4 17:42:44 2000
+++ ./lib/Event.pm      Mon Feb  7 16:22:05 2000
@@ -13,7 +13,7 @@ use Carp;
 eval { require Carp::Heavy; };  # work around perl_call_pv bug XXX
 use vars qw($VERSION @EXPORT_OK
            $API $DebugLevel $Eval $DIED $Now);
-$VERSION = '0.64';
+$VERSION = '0.65';
 
 # If we inherit DynaLoader then we inherit AutoLoader; Bletch!
 require DynaLoader;
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/lib/Event.pod' 
'/usr/tmp/mp4384.d/new/Event-0.65/lib/Event.pod'
Index: ./lib/Event.pod
--- ./lib/Event.pod     Fri Feb  4 17:39:18 2000
+++ ./lib/Event.pod     Mon Feb  7 13:08:50 2000
@@ -181,8 +181,8 @@ Reports whether the C<$watcher> is suspe
 
 =item $watcher->pending
 
-Returns how many events this watcher has with the callback still pending
-in the event queue.
+Returns whether this watcher has any events pending in the event
+queue.
 
 =back
 
@@ -211,7 +211,7 @@ Otherwise, they might be deprecated.
 
 =item var
 
-Extra attributes: var => \$var, poll => 'rw', got => 'rw',
+Extra attributes: var => \$var, poll => 'rw'
 
 Var watchers generate events when the given variable is read from or
 written to.
@@ -237,7 +237,7 @@ calculated relative to the current time 
 
 =item io
 
-Extra attributes: fd => $fd, poll => 'rwe', got => 'rwet',
+Extra attributes: fd => $fd, poll => 'rwe'
 [timeout => $seconds, hard => $bool, timeout_cb => \&code]
 
 The callback is invoked when the file descriptor, C<fd>, has data to
@@ -269,7 +269,8 @@ Not yet implemented.
 Priority is used to sort the event queue.  Meaningful priorities range
 from -1 to 6 inclusive.  Lower numbers mean higher priority (-1 is the
 highest priority and 6 is the lowest).  If multiple events get queued,
-the ones with the highest priority are serviced first.
+the ones with the highest priority are serviced first.  Events with
+equal priority are serviced in first-in-first-out order.
 
   use Event qw(PRIO_HIGH PRIO_NORMAL);   # some constants
 
@@ -485,7 +486,7 @@ A reference to the variable being watche
 C<got> is available in the callback of watchers with C<poll>.
 C<got> is in the same format as C<poll> except that it gives what
 kind of event actually happened.  In contrast, C<poll> is just an
-expression of interest.
+indication of interest.
 
 =item hits => $int
 
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/lib/Event/EventAPI.h' 
'/usr/tmp/mp4384.d/new/Event-0.65/lib/Event/EventAPI.h'
Index: ./lib/Event/EventAPI.h
--- ./lib/Event/EventAPI.h      Tue Feb  1 12:18:15 2000
+++ ./lib/Event/EventAPI.h      Mon Feb  7 13:28:45 2000
@@ -28,7 +28,7 @@ struct pe_watcher {
     pe_ring all;       /* all watchers */
     pe_ring events;    /* this watcher's queued events */
     HV *FALLBACK;
-    I16 event_counter; /* refcnt? XXX */
+    I16 refcnt;                /* internal to Event; not perl related */
     I16 prio;
     I16 max_cb_tm;
 };
@@ -146,6 +146,16 @@ struct pe_var {
     pe_watcher base;
     SV *variable;
     U16 events;
+};
+
+typedef struct pe_group pe_group;
+struct pe_group {
+    pe_watcher base;
+    double since;
+    pe_timeable tm;
+    SV *timeout;
+    int members;
+    pe_watcher **member;
 };
 
 typedef struct pe_event_stats_vtbl pe_event_stats_vtbl;
gdiff -up /dev/null '/usr/tmp/mp4384.d/new/Event-0.65/lib/Event/group.pm'
Index: ./lib/Event/group.pm
--- ./lib/Event/group.pm        Wed Dec 31 19:00:00 1969
+++ ./lib/Event/group.pm        Mon Feb  7 16:15:17 2000
@@ -0,0 +1,30 @@
+use strict;
+package Event::group;
+use Carp;
+use base 'Event::Watcher';
+use vars qw(@ATTRIBUTE);
+
+@ATTRIBUTE = qw(timeout);
+
+'Event::Watcher'->register;
+
+sub new {
+    my $class = shift;
+    my %arg;
+    my @add;
+    while (my ($k,$v) = splice(@_, 0, 2)) {
+       if ($k eq 'add') {
+           push @add, $v;
+       } elsif ($k eq 'del') {
+           carp "del in constructor (ignored)";
+       } else {
+           $arg{$k} = $v;
+       }
+    }
+    my $o = allocate($class, delete $arg{attach_to} || {});
+    $o->init(\%arg);
+    $o->add($_) for @add;
+    $o;
+}
+
+1;
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/t/attach_to.t' 
'/usr/tmp/mp4384.d/new/Event-0.65/t/attach_to.t'
Index: ./t/attach_to.t
--- ./t/attach_to.t     Fri Feb  4 08:14:42 2000
+++ ./t/attach_to.t     Mon Feb  7 15:23:15 2000
@@ -6,9 +6,9 @@ use Event 0.53;
 
 # $Event::DebugLevel = 3;
 
-my $array = Event->timer(attach_to => [0,1,2], after => 1);
+my $array = Event->timer(attach_to => [0,1,2], after => 1, cb => \&die);
 ok $array->[2], 2;
 ok $array->interval, 1;
 
-eval { Event->timer(attach_to => bless([]), after => 1); };
+eval { Event->timer(attach_to => bless([]), after => 1, cb => \&die); };
 ok $@, '/blessed/';
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/t/bored.t' 
'/usr/tmp/mp4384.d/new/Event-0.65/t/bored.t'
Index: ./t/bored.t
--- ./t/bored.t Fri Feb  4 08:14:49 2000
+++ ./t/bored.t Mon Feb  7 15:24:26 2000
@@ -5,17 +5,18 @@ use Event;
 # $Event::DebugLevel = 3;
 
 my $really_bored;
-my $e;
-$e = Event->timer(after => .5);
-ok !defined $e->cb;
-$e->cb(sub {
+my $w;
+$w = Event->timer(after => .5, parked => 1);
+ok !defined $w->cb;
+$w->cb(sub {
           if (!$really_bored) {
-              $e->again;
+              $w->again;
               $really_bored='yes';
           } else {
               ok 1;
           }
        });
-ok ref $e->cb, 'CODE';
+ok ref $w->cb, 'CODE';
+$w->start;
 
 ok !defined Event::loop();
gdiff -up /dev/null '/usr/tmp/mp4384.d/new/Event-0.65/t/fifo.t'
Index: ./t/fifo.t
--- ./t/fifo.t  Wed Dec 31 19:00:00 1969
+++ ./t/fifo.t  Mon Feb  7 15:26:14 2000
@@ -0,0 +1,29 @@
+#!./perl -w
+# check FIFO dispatch of equal priority events
+
+use Test; plan test => 1;
+use Event;
+
+my @hit;
+sub cb {
+    my ($e) = @_;
+    push @hit, $e->w->desc;
+}
+
+my $t1 = Event->timer(desc => 1, after => 10, cb => \&cb);
+my $t2 = Event->timer(desc => 2, after => 10, cb => \&cb);
+my $t3 = Event->timer(desc => 3, after => 10, cb => \&cb);
+my $h4 = Event->timer(desc => 4, nice => -1, after => 10, cb => \&cb);
+my $h5 = Event->timer(desc => 5, nice => -1, after => 10, cb => \&cb);
+
+$t2->now;
+$h4->now;
+$t1->now;
+$t1->now;
+$t3->now;
+$h5->now;
+$t2->now;
+$t1->now;
+
+Event::loop();
+ok join('', @hit), '45211321';
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/t/leak.t' 
'/usr/tmp/mp4384.d/new/Event-0.65/t/leak.t'
Index: ./t/leak.t
--- ./t/leak.t  Fri Feb  4 08:15:58 2000
+++ ./t/leak.t  Mon Feb  7 15:27:22 2000
@@ -8,12 +8,12 @@ ok @e, 0;
 ok @e, 0;
 
 sub thrash {
-    Event->idle()->cancel;
+    Event->idle(parked=>1)->cancel;
     Event->io(parked => 1)->cancel;
-    Event->signal(signal => 'INT')->cancel;
-    Event->timer(at => time)->cancel;
+    Event->signal(parked=>1)->cancel;
+    Event->timer(parked=>1)->cancel;
     my $var = 1;
-    Event->var(var => \$var)->cancel;
+    Event->var(parked=>1)->cancel;
 }
 for (1..2) { thrash(); }
 
gdiff -up '/usr/tmp/mp4384.d/old/Event-0.64/t/unconfigured.t' 
'/usr/tmp/mp4384.d/new/Event-0.65/t/unconfigured.t'
Index: ./t/unconfigured.t
--- ./t/unconfigured.t  Fri Feb  4 08:17:57 2000
+++ ./t/unconfigured.t  Mon Feb  7 15:32:13 2000
@@ -1,28 +1,27 @@
 #!./perl -w
 
 use strict;
-use Test; plan test => 7;
+use Test; plan test => 6;
 use Event;
 
-eval { Event->io };
+my @p = (cb=>\&die);
+
+eval { Event->io(@p) };
 ok $@, '/unconfigured/';
 
-eval { Event->signal };
-ok $@, '/no signal/';
+eval { Event->signal(@p) };
+ok $@, '/without signal/';
 
-eval { Event->timer };
+eval { Event->timer(@p) };
 ok $@, '/unset/';
 
-eval { Event->timer(parked => 1, interval => -1)->again };
-ok $@, '/non\-positive/';
-
-eval { Event->var };
+eval { Event->var(@p) };
 ok $@, '/watching what/';
 
 my $var = 1;
 
-eval { Event->var(poll => 0, var => \$var) };
-ok $@, '/no poll events/';
+eval { Event->var(@p, poll => 0, var => \$var) };
+ok $@, '/without poll events/';
 
-eval { Event->var(var => \$1) };
+eval { Event->var(@p, var => \$1) };
 ok $@, '/read\-only/';
#### End of Patch data ####

#### ApplyPatch data follows ####
# Data version        : 1.0
# Date generated      : Mon Feb  7 16:30:13 2000
# Generated by        : makepatch 2.00 (2.0BETA)
# Recurse directories : Yes
# p 'ChangeLog' 21762 949958518 0100444
# p 'Event.h' 4576 949954758 0100444
# p 'Event.xs' 17402 949954604 0100444
# p 'MANIFEST' 845 949958463 0100444
# p 'TODO' 1921 949958975 0100444
# p 'c/ev.c' 7871 949948015 0100444
# c 'c/group.c' 0 949958231 0100444
# p 'c/idle.c' 3544 949936508 0100444
# p 'c/io.c' 5222 949936635 0100444
# p 'c/signal.c' 3788 949936675 0100444
# p 'c/timer.c' 2150 949947894 0100444
# p 'c/typemap.c' 3806 949947924 0100444
# p 'c/var.c' 4082 949936722 0100444
# p 'c/watcher.c' 8955 949947995 0100444
# c 'demo/group.t' 0 949958444 0100444
# p 'lib/Event.pm' 4254 949958525 0100444
# p 'lib/Event.pod' 21895 949946930 0100444
# p 'lib/Event/EventAPI.h' 5379 949948125 0100444
# c 'lib/Event/group.pm' 0 949958117 0100444
# p 't/attach_to.t' 280 949954995 0100444
# p 't/bored.t' 339 949955066 0100444
# c 't/fifo.t' 0 949955174 0100444
# p 't/leak.t' 659 949955242 0100444
# p 't/unconfigured.t' 476 949955533 0100444
#### End of ApplyPatch data ####

#### End of Patch kit [created: Mon Feb  7 16:30:13 2000] ####
#### Checksum: 896 25763 48850 ####

-- 
"May the best description of competition prevail."
           via, but not speaking for Deutsche Bank

Reply via email to