cvsuser     04/01/07 07:22:04

  Modified:    classes  timer.pmc
               t/pmc    timer.t
  Log:
  event-handling-14
  event-handling-14
  * use event queue for timer events
  
  Revision  Changes    Path
  1.8       +61 -219   parrot/classes/timer.pmc
  
  Index: timer.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/classes/timer.pmc,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -w -r1.7 -r1.8
  --- timer.pmc 25 Aug 2003 09:46:23 -0000      1.7
  +++ timer.pmc 7 Jan 2004 15:22:02 -0000       1.8
  @@ -1,7 +1,7 @@
   /* timer.pmc
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: timer.pmc,v 1.7 2003/08/25 09:46:23 leo Exp $
  + *     $Id: timer.pmc,v 1.8 2004/01/07 15:22:02 leo Exp $
    *  Overview:
    *     This is the Timer base class
    *  Data Structure and Algorithms:
  @@ -12,14 +12,14 @@
    *  History:
    *     Initial proposal by leo 2003.07.15
    *     Initial revision        2003.07.17
  + *     Switch to events        2004.01.07
    *  Synopsis:
    *     new P0, .Timer
    *     set P0[.PARROT_TIMER_SEC], I_seconds        # whole seconds
    *     set P0[.PARROT_TIMER_USEC], I_micro seconds # and/or micro seconds
    *     set P0[.PARROT_TIMER_NSEC], N_seconds_frac  # or fraction in seconds
    *     set P0[.PARROT_TIMER_REPEAT], I_repeat      # 0 = one shot ...
  - *     set_addr I0, _subroutine
  - *     set P0, I0                                  # set timer handler sub
  + *     set P0[.PARROT_TIMER_HANDLER], P_sub        # set handler sub PMC
    *     invoke P0                                   # start timer
    *     set P0[.PARROT_TIMER_RUNNING], 1            # same
    *
  @@ -50,10 +50,6 @@
   #include "parrot/parrot.h"
   #include "parrot/method_util.h"
   
  -/*
  - * for now we keep all stuff inside the pmc
  - */
  -
   /* interface constants */
   /* &gen_from_enum(timer.pasm) */
   typedef enum {
  @@ -67,190 +63,31 @@
   } parrot_timer_enum_t;
   /* &end_gen */
   
  -/* internal run state */
  -typedef enum {
  -    PARROT_TIMER_STATE_STOPPED,
  -    PARROT_TIMER_STATE_NEW,
  -    PARROT_TIMER_STATE_RUNNING,
  -    PARROT_TIMER_STATE_FIRE
  -} parrot_timer_state_t;
  -
  -typedef struct parrot_timer_t {
  -    int flags;
  -    int ticks;
  -    int value;
  -    int repeat;
  -    int state;
  -    union {
  -     INTVAL pasm_code;
  -     void *c_code;
  -    } handler;
  -    PMC *self;
  -    struct parrot_timer_t *next;
  -    struct parrot_timer_t *prev;
  -} parrot_timer_t;
  -
  -/* XXX next 2 should probably go into interpreter */
  -/* linked list of running timers */
  -static parrot_timer_t *rtimer = 0;
  -/* handle of system timer */
  -static void *handle = (void *) -1;
  -
  -/* add timer to running */
   static void
  -add_timer(parrot_timer_t *t)
  +add_timer(Parrot_Interp interpreter, PMC *pmc)
   {
  -    parrot_timer_t *next = rtimer;
  -    rtimer = t;
  -    t->next = next;
  -    if (next) {
  -     next->prev = t;
  -    }
  -    t->state = PARROT_TIMER_STATE_RUNNING;
  -    PObj_needs_early_DOD_SET(t->self);
  +    parrot_timer_event *t = pmc->cache.struct_val;
  +    /* TODO handle interval, repeat count */
  +    if (!PMC_IS_NULL(t->sub))
  +     Parrot_new_timer_event(interpreter, t->abs_time, 0, t->sub);
   }
   
  -static int
  -timer_is_running(parrot_timer_t *tp)
  -{
  -    parrot_timer_t *t;
  -    /* be paranoid, check run lis too */
  -    for (t = rtimer; t; t = t->next)
  -     if (t == tp)
  -         return 1;
  -    return 0;
  -}
  -
  -/* del timer from running */
   static void
  -del_timer(parrot_timer_t *t)
  +del_timer(Parrot_Interp interpreter, PMC *pmc)
   {
  -    parrot_timer_t *next = t->next;
  -    parrot_timer_t *prev = t->prev;
  -
  -    if (!timer_is_running(t))
  -     return;
  -    if (prev)
  -     prev->next = next;
  -    else
  -     rtimer = next;
  -    if (next)
  -     next->prev = prev;
  -    t->ticks = 0;
  -    t->state = PARROT_TIMER_STATE_STOPPED;
  -    PObj_needs_early_DOD_CLEAR(t->self);
  -}
  -
  -/* TODO move this to misc.c (or util.c?), s. also math.ops */
  -static UINTVAL
  -gcd(UINTVAL a, UINTVAL b)
  -{
  -
  -    UINTVAL q = 0;
  -    UINTVAL c = 0;
  -    while (b != 0) {
  -     q = (UINTVAL)floor( (FLOATVAL)a/b );
  -     c = a - b*q;
  -     a = b;
  -     b = c;
  -    }
  -    return a;
  +    /* TODO find timer in queue, set inactive flag */
   }
   
  -static void
  -recalc_ticks(void)
  -{
  -    UINTVAL ms, oms;
  -    parrot_timer_t *t;
   
  -    oms = get_sys_timer_ms(handle);
  -    t = rtimer;
  -    if (t) {
  -     if (t->state == PARROT_TIMER_STATE_NEW)
  -         t->state = PARROT_TIMER_STATE_STOPPED;
  -     if (oms && t->ticks)
  -         ms = oms*t->ticks;  /* time left */
  -     else
  -         ms = t->value;
  -     if (t->next) {
  -         for (t = t->next; t; t = t->next) {
  -             if (t->state == PARROT_TIMER_STATE_NEW)
  -                 t->state = PARROT_TIMER_STATE_STOPPED;
  -             if (oms && t->ticks) {
  -                 ms = gcd(oms*t->ticks, ms);
  -             }
  -             else
  -                 ms = gcd(t->value, ms);
  -         }
  -     }
  -     for (t = rtimer; t; t = t->next) {
  -         int ot = t->ticks;
  -         if (oms && ot)
  -             t->ticks = t->ticks * ((double)oms / (double)ms);
  -         else
  -             t->ticks = t->value / ms;
  -         if (!t->ticks) {
  -             internal_exception(1, "Timer ticks are zero\n");
  -         }
  -     }
  -    }
  -    else
  -     ms = 0;
  -
  -    if (ms)
  -     start_sys_timer_ms(handle, ms);
  -    else
  -     stop_sys_timer_ms(handle);
  -}
  -
  -static void
  -do_alarm_handler(void)
  -{
  -    parrot_timer_t *t;
  -    UINTVAL ms;
  -    int recalc = 0;
  -
  -    ms = get_sys_timer_ms(handle);
  -    for (t = rtimer; t; t = t->next) {
  -     if (!--t->ticks) {
  -         t->state = PARROT_TIMER_STATE_FIRE;
  -         if (t->repeat) {
  -             t->ticks = t->value/ms;
  -             if (t->repeat != -1)
  -                 t->repeat--;
  -         }
  -     }
  -    }
  -    /* do this in a separate loop, and always start over:
  -     * the timer handler function might add/stop timers
  -     */
  -again:
  -    for (t = rtimer; t; t= t->next) {
  -     if (t->state == PARROT_TIMER_STATE_FIRE) {
  -         t->state = PARROT_TIMER_STATE_RUNNING;
  -         /* TODO setup event */
  -         goto again;
  -     }
  -     if (!t->ticks && !t->repeat) {
  -         del_timer(t);
  -         recalc = 1;
  -         goto again;
  -     }
  -    }
  -    if (recalc)
  -     recalc_ticks();
  -}
  -
  -pmclass Timer {
  -    void class_init() {
  -     if (handle == (void *) -1)
  -         handle = new_sys_timer_ms();
  -    }
  +pmclass Timer does event {
   
       void init() {
  -     parrot_timer_t *t = mem_sys_allocate_zeroed(sizeof(parrot_timer_t));
  -     t->state = PARROT_TIMER_STATE_NEW;
  -     t->self = SELF;
  +     /*
  +      * t->abs_time actually is relative, its converted to an
  +      * absolute time, when the timer is started
  +      */
  +     parrot_timer_event *t =
  +         mem_sys_allocate_zeroed(sizeof(parrot_timer_event));
        SELF->cache.struct_val = t;
           PObj_active_destroy_SET(SELF);
        interpreter->has_early_DOD_PMCs = 1;
  @@ -264,6 +101,7 @@
        INTVAL i;
        INTVAL val;
        FLOATVAL nval;
  +     PMC *pval;
   
        SELF.init();
        for (i = 0; i < n; i += 2) {
  @@ -273,7 +111,6 @@
                case PARROT_TIMER_USEC:
                case PARROT_TIMER_REPEAT:
                case PARROT_TIMER_RUNNING:
  -             case PARROT_TIMER_HANDLER:
                    val =
                        VTABLE_get_integer_keyed_int(interpreter, init, i+1);
                    SELF.set_integer_keyed_int(key, val);
  @@ -283,103 +120,108 @@
                        VTABLE_get_number_keyed_int(interpreter, init, i+1);
                    SELF.set_number_keyed_int(key, nval);
                    break;
  +             case PARROT_TIMER_HANDLER:
  +                 pval =
  +                     VTABLE_get_pmc_keyed_int(interpreter, init, i+1);
  +                 SELF.set_pmc_keyed_int(key, pval);
  +                 break;
            }
        }
       }
   
       void destroy() {
  -     parrot_timer_t *t = SELF->cache.struct_val;
  -     del_timer(t);
  +     parrot_timer_event *t = SELF->cache.struct_val;
  +     del_timer(INTERP, SELF);
        mem_sys_free(t);
       }
   
       INTVAL get_integer_keyed_int(INTVAL key) {
  -     parrot_timer_t *t = SELF->cache.struct_val;
  +     parrot_timer_event *t = SELF->cache.struct_val;
   
        switch(key) {
            case PARROT_TIMER_SEC:
  -             return t->value/1000;
  +             return (INTVAL)t->abs_time;
                break;
            case PARROT_TIMER_USEC:
  -             return (t->value % 1000) * 1000;
  +             return (t->abs_time - (INTVAL)t->abs_time) *1000000.0;
                break;
            case PARROT_TIMER_REPEAT:
  -             return t->repeat;
  -             break;
            case PARROT_TIMER_RUNNING:
  -             return timer_is_running(t);
  +             return 0;
                break;
  +     }
  +     return -1;
  +    }
  +
  +    PMC* get_pmc_keyed_int(INTVAL key) {
  +     parrot_timer_event *t = SELF->cache.struct_val;
  +     switch(key) {
            case PARROT_TIMER_HANDLER:
  -             return t->handler.pasm_code;
  +             return t->sub;
                break;
  +         default:
  +             return PMCNULL;
        }
  -     return -1;
  +     return PMCNULL;
       }
   
       FLOATVAL get_number_keyed_int(INTVAL key) {
  -     parrot_timer_t *t = SELF->cache.struct_val;
  +     parrot_timer_event *t = SELF->cache.struct_val;
   
        switch(key) {
            case PARROT_TIMER_NSEC:
  -             return (FLOATVAL)t->value/1000.0;
  +             return t->abs_time;
                break;
        }
        return -1.0;
       }
   
  -    void set_integer_native(INTVAL value) {
  -     parrot_timer_t *t = SELF->cache.struct_val;
  -     t->handler.pasm_code = value;
  -    }
  -
       void set_integer_keyed_int(INTVAL key, INTVAL value) {
  -     parrot_timer_t *t = SELF->cache.struct_val;
  +     parrot_timer_event *t = SELF->cache.struct_val;
   
        switch(key) {
            case PARROT_TIMER_SEC:
  -             t->value = value * 1000;
  +             t->abs_time = value;
                break;
            case PARROT_TIMER_USEC:
  -             t->value += value / 1000;
  +             t->abs_time += value / 1000000.0;
                break;
            case PARROT_TIMER_REPEAT:
  -             t->repeat = value;
  +             /* t->repeat = value; */
                break;
            case PARROT_TIMER_RUNNING:
                if (value) {
  -                 if (!timer_is_running(t)) {
  -                     add_timer(t);
  -                     recalc_ticks();
  -                 }
  +                 add_timer(INTERP, SELF);
                }
                else {
  -                 if (timer_is_running(t)) {
  -                     del_timer(t);
  -                     recalc_ticks();
  -                 }
  +                 del_timer(INTERP, SELF);
                }
                break;
  +     }
  +    }
  +
  +    void set_pmc_keyed_int(INTVAL key, PMC* value) {
  +     parrot_timer_event *t = SELF->cache.struct_val;
  +     switch(key) {
            case PARROT_TIMER_HANDLER:
  -             t->handler.pasm_code = value;
  +             t->sub = value;
  +             break;
  +         default:
                break;
        }
       }
   
       void* invoke(void *next) {
  -     parrot_timer_t *t = SELF->cache.struct_val;
  -     if (!timer_is_running(t)) {
  -         add_timer(t);
  -         recalc_ticks();
  -     }
  +     add_timer(INTERP, SELF);
        return next;
       }
   
       void set_number_keyed_int(INTVAL key, FLOATVAL value) {
  -     parrot_timer_t *t = SELF->cache.struct_val;
  +     parrot_timer_event *t = SELF->cache.struct_val;
   
        switch(key) {
            case PARROT_TIMER_NSEC:
  -             t->value = (INTVAL) (value * 1000.0);
  +             t->abs_time = value;
                break;
        }
       }
  
  
  
  1.3       +16 -18    parrot/t/pmc/timer.t
  
  Index: timer.t
  ===================================================================
  RCS file: /cvs/public/parrot/t/pmc/timer.t,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -w -r1.2 -r1.3
  --- timer.t   30 Jul 2003 08:05:24 -0000      1.2
  +++ timer.t   7 Jan 2004 15:22:04 -0000       1.3
  @@ -63,37 +63,35 @@
   ok 3
   OUT
   
  +SKIP: {
  +  skip("No thread config yet", 1) unless ($^O eq 'linux' or $^O eq 'darwin');
  +
   output_is(<<'CODE', <<'OUT', "Timer setup - initializer/start");
   .include "timer.pasm"
  +    bounds 1 # cant run with JIT core yet
       new P1, .SArray
       set P1, 6
  -    set P1[0], .PARROT_TIMER_SEC
  -    set P1[1], 8
  -    set P1[2], .PARROT_TIMER_USEC
  -    set P1[3], 400000
  +    set P1[0], .PARROT_TIMER_NSEC
  +    set P1[1], 0.5
  +    set P1[2], .PARROT_TIMER_HANDLER
  +    find_global P2, "_timer_sub"
  +    set P1[3], P2
       set P1[4], .PARROT_TIMER_RUNNING
       set P1[5], 1
   
       new P0, .Timer, P1
  -    set I0, P0[.PARROT_TIMER_SEC]
  -    eq I0, 8, ok1
  -    print "not "
  -ok1:
       print "ok 1\n"
  -    set I0, P0[.PARROT_TIMER_USEC]
  -    eq I0, 400000, ok2
  -    print "not "
  -ok2:
  -    print "ok 2\n"
  -
  -    set I0, P0[.PARROT_TIMER_RUNNING]
  -    eq I0, 1, ok3
  -    print "not "
  -ok3:
  +    sleep 1
       print "ok 3\n"
       end
  +.pcc_sub _timer_sub:
  +    print "ok 2\n"
  +    invoke P1
   CODE
   ok 1
   ok 2
   ok 3
   OUT
  +
  +}
  +
  
  
  

Reply via email to