cvsuser     04/01/18 01:52:24

  Modified:    src      events.c
  Log:
  event-handling-18
  * fix a race: the interpreter sometimes processed events already
    while the event thread was still looking at that event, which
    was NULL in the meantime
  * cleanup - separate process_events func
  
  Revision  Changes    Path
  1.21      +95 -68    parrot/src/events.c
  
  Index: events.c
  ===================================================================
  RCS file: /cvs/public/parrot/src/events.c,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -w -r1.20 -r1.21
  --- events.c  17 Jan 2004 19:59:19 -0000      1.20
  +++ events.c  18 Jan 2004 09:52:23 -0000      1.21
  @@ -1,7 +1,7 @@
   /* events.c
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: events.c,v 1.20 2004/01/17 19:59:19 leo Exp $
  + *     $Id: events.c,v 1.21 2004/01/18 09:52:23 leo Exp $
    *  Overview:
    *     Event handling stuff
    *  Data Structure and Algorithms:
  @@ -213,14 +213,21 @@
       Parrot_schedule_event(NULL, ev);
   }
   
  +/*
  + * put a queue entry into the interpreters task queue
  + */
   void
   Parrot_schedule_interp_qentry(Parrot_Interp interpreter, QUEUE_ENTRY* entry)
   {
       parrot_event* event;
  -    push_entry(interpreter->task_queue, entry);
       event = entry->data;
       if (event->type != EVENT_TYPE_SLEEP)
           enable_event_checking(interpreter);
  +    /*
  +     * do push_entry last - this signales the queue condition so the
  +     * interpreter might starting process that event immediately
  +     */
  +    push_entry(interpreter->task_queue, entry);
   }
   
   /*
  @@ -240,48 +247,23 @@
       event->u.timer_event.abs_time = now + event->u.timer_event.interval;
       return new_entry;
   }
  +
   /*
  - * The event_thread is started by the first interpreter.
  - * It handles all events for all interpreters.
  + * do something, when an event arrived caller has locked the mutex
  + * returns 0 if event thread terminates
    */
  -static void*
  -event_thread(void *data)
  +static int
  +process_events(QUEUE* event_q)
   {
  -    QUEUE* event_q = (QUEUE*) data;
  -    parrot_event* event;
  +    FLOATVAL now;
       QUEUE_ENTRY *entry;
  +    parrot_event* event;
   
  -    LOCK(event_q->queue_mutex);
  -    while (1) {
  -        entry = peek_entry(event_q);
  -        if (!entry) {
  -            /* wait infinite until entry arrives */
  -            queue_wait(event_q);
  -        }
  -        else if (entry->type == QUEUE_ENTRY_TYPE_TIMED_EVENT) {
  -            /* do a_timedwait for entry */
  -            struct timespec abs_time;
  -            FLOATVAL when;
  -            event = (parrot_event* )entry->data;
  -            when = event->u.timer_event.abs_time;
  -            abs_time.tv_sec = (time_t) when;
  -            abs_time.tv_nsec = (when - abs_time.tv_sec) * (1000L*1000L*1000L);
  -
  -            queue_timedwait(event_q, &abs_time);
  -        }
  -        else {
  -            /* we shouldn't get here probably
  -             * - the event queue terminating event is seen here
  -             */
  -
  -        }
  +    while (( entry = peek_entry(event_q))) {
           /*
            * one or more entries arrived - we hold the mutex again
            * so we have to use the nonsyc_pop_entry to pop off event entries
            */
  -        while (( entry = peek_entry(event_q))) {
  -            FLOATVAL now;
  -
               event = NULL;
               switch (entry->type) {
                   case QUEUE_ENTRY_TYPE_EVENT:
  @@ -297,7 +279,7 @@
                        * wait until we get at it again when time has elapsed
                        */
                       if (now < event->u.timer_event.abs_time)
  -                        goto again;
  +                    return 1;
                       entry = nosync_pop_entry(event_q);
                       /*
                        * if event is repeated dup and reinsert it
  @@ -314,17 +296,16 @@
                   default:
                       internal_exception(1, "Unknown queue entry");
               }
  -            /*
  -             * TODO check for a stop event to do cleanup
  -             */
               assert(event);
               if (event->type == EVENT_TYPE_NONE) {
                   mem_sys_free(entry);
  +            mem_sys_free(event);
                   continue;
               }
               else if (event->type == EVENT_TYPE_EVENT_TERMINATE) {
                   mem_sys_free(entry);
  -                goto out;
  +            mem_sys_free(event);
  +            return 0;
               }
               /*
                * now insert entry in interpreter task queue
  @@ -337,16 +318,62 @@
                    * TODO broadcast or deliver to first interp
                    */
                   mem_sys_free(entry);
  +            mem_sys_free(event);
               }
           } /* while events */
  -again:
  -        ;
  +    return 1;
  +}
  +
  +/*
  + * The event_thread is started by the first interpreter.
  + * It handles all events for all interpreters.
  + */
  +static void*
  +event_thread(void *data)
  +{
  +    QUEUE* event_q = (QUEUE*) data;
  +    parrot_event* event;
  +    QUEUE_ENTRY *entry;
  +    int running = 1;
  +
  +    LOCK(event_q->queue_mutex);
  +    /*
  +     * we might already have an event in the queue
  +     */
  +    if (peek_entry(event_q))
  +        running = process_events(event_q);
  +    while (running) {
  +        entry = peek_entry(event_q);
  +        if (!entry) {
  +            /* wait infinite until entry arrives */
  +            queue_wait(event_q);
  +        }
  +        else if (entry->type == QUEUE_ENTRY_TYPE_TIMED_EVENT) {
  +            /* do a_timedwait for entry */
  +            struct timespec abs_time;
  +            FLOATVAL when;
  +            event = (parrot_event* )entry->data;
  +            when = event->u.timer_event.abs_time;
  +            abs_time.tv_sec = (time_t) when;
  +            abs_time.tv_nsec = (when - abs_time.tv_sec) * (1000L*1000L*1000L);
  +
  +            queue_timedwait(event_q, &abs_time);
  +        }
  +        else {
  +            /* we shouldn't get here probably
  +             */
  +            internal_exception(1, "Spurious event");
  +
  +        }
  +        /*
  +         * one or more entries arrived - we hold the mutex again
  +         * so we have to use the nonsyc_pop_entry to pop off event entries
  +         */
  +        running = process_events(event_q);
       } /* event loop */
  -out:
       /*
        * the main interpreter is dying
        */
  -    mem_sys_free(event);
       UNLOCK(event_q->queue_mutex);
       queue_destroy(event_q);
       return NULL;
  
  
  

Reply via email to