[svn:parrot] r47764 - in branches/gsoc_threads: config/gen/makefiles include/parrot src src/pmc t/pmc

Chandon at svn.parrot.org Chandon at svn.parrot.org
Tue Jun 22 18:14:51 UTC 2010


Author: Chandon
Date: Tue Jun 22 18:14:50 2010
New Revision: 47764
URL: https://trac.parrot.org/parrot/changeset/47764

Log:
Add alarm mechanism; not yet hooked into anything.

Added:
   branches/gsoc_threads/include/parrot/alarm.h
   branches/gsoc_threads/include/parrot/alarm_private.h
   branches/gsoc_threads/src/alarm.c
   branches/gsoc_threads/src/pmc/alarmtest.pmc
   branches/gsoc_threads/src/pmc/pmclist.pmc
   branches/gsoc_threads/t/pmc/pmclist.t
Modified:
   branches/gsoc_threads/config/gen/makefiles/root.in
   branches/gsoc_threads/src/main.c
   branches/gsoc_threads/src/pmc/scheduler.pmc
   branches/gsoc_threads/src/scheduler.c

Modified: branches/gsoc_threads/config/gen/makefiles/root.in
==============================================================================
--- branches/gsoc_threads/config/gen/makefiles/root.in	Tue Jun 22 17:37:26 2010	(r47763)
+++ branches/gsoc_threads/config/gen/makefiles/root.in	Tue Jun 22 18:14:50 2010	(r47764)
@@ -445,6 +445,7 @@
     src/exit$(O) \
     src/extend$(O) \
     src/extend_vtable$(O) \
+	src/alarm$(O) \
     src/gc/alloc_memory$(O) \
     src/gc/api$(O) \
     src/gc/gc_ms$(O) \
@@ -915,6 +916,10 @@
 	$(INC_DIR)/scheduler_private.h \
 	$(INC_DIR)/runcore_api.h
 
+src/alarm$(O) : $(PARROT_H_HEADERS) src/alarm.c \
+	$(INC_DIR)/alarm.h \
+	$(INC_DIR)/alarm_private.h
+
 src/io/core$(O) : $(PARROT_H_HEADERS) src/io/io_private.h src/io/core.c
 
 src/io/socket_api$(O) : $(PARROT_H_HEADERS) src/io/io_private.h \

Added: branches/gsoc_threads/include/parrot/alarm.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_threads/include/parrot/alarm.h	Tue Jun 22 18:14:50 2010	(r47764)
@@ -0,0 +1,40 @@
+/*
+Copyright (C) 2010, Parrot Foundation.
+$Id$
+*/
+
+#ifndef PARROT_ALARM_H_GUARD
+#define PARROT_ALARM_H_GUARD
+
+typedef unsigned int Parrot_alarm_state;
+
+/* HEADERIZER BEGIN: src/alarm.c */
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
+
+PARROT_EXPORT
+void Parrot_alarm_init(void);
+
+PARROT_EXPORT
+void Parrot_alarm_set(FLOATVAL when);
+
+PARROT_EXPORT
+int Parrot_alarm_check(Parrot_alarm_state* last_serial);
+
+void Parrot_alarm_callback(NULLOK(int sig_number));
+void Parrot_alarm_set(FLOATVAL wait);
+#define ASSERT_ARGS_Parrot_alarm_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_alarm_set __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_alarm_triggered __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_alarm_callback __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_alarm_set __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
+/* HEADERIZER END: src/alarm.c */
+
+#endif /* PARROT_ALARM_H_GUARD */
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Added: branches/gsoc_threads/include/parrot/alarm_private.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_threads/include/parrot/alarm_private.h	Tue Jun 22 18:14:50 2010	(r47764)
@@ -0,0 +1,24 @@
+/*
+Copyright (C) 2010, Parrot Foundation.
+$Id$
+*/
+
+#ifndef PARROT_ALARM_PRIVATE_GUARD_H
+#define PARROT_ALARM_PRIVATE_GUARD_H
+
+#include "parrot.h"
+
+typedef struct Parrot_alarm_queue {
+    FLOATVAL when;
+    int alarm_set;
+    struct Parrot_alarm_queue *next;
+} Parrot_alarm_queue;
+
+#endif /* PARROT_ALARM_PRIVATE_GUARD_H */
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Added: branches/gsoc_threads/src/alarm.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_threads/src/alarm.c	Tue Jun 22 18:14:50 2010	(r47764)
@@ -0,0 +1,194 @@
+/*
+Copyright (C) 2010, Parrot Foundation.
+$Id$
+
+=head1 NAME
+
+src/alarm.c - Implements a mechanism for alarms, setting a flag after a delay.
+
+=cut
+
+*/
+
+#include "parrot/alarm_private.h"
+#include "parrot/alarm.h"
+
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
+/* HEADERIZER END: src/alarm.c */
+
+/* Some per-process state */
+static Parrot_alarm_queue* alarm_queue;
+static volatile unsigned int alarm_serial;
+
+/* This file relies on POSIX. Probably need two other versions of it: 
+ *  one for Windows and one for platforms with no signals or threads. */
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+
+/* HEADERIZER HFILE: include/parrot/alarm.h */
+
+/*
+=head1 Parrot_alarm_init()
+
+Initialize the alarm queue. This function should only be called from the initial
+pthread. Any other pthreads should make sure to mask out SIGALRM.
+
+=cut
+*/
+
+void Parrot_alarm_callback(SHIM(int sig_number));
+
+PARROT_EXPORT
+void
+Parrot_alarm_init(void)
+{
+    struct sigaction sa;
+    sa.sa_handler = Parrot_alarm_callback;
+    sa.sa_flags   = SA_RESTART;
+
+    if(sigaction(SIGALRM, &sa, 0) == -1) {
+        perror("sigaction failed in Parrot_timers_init");
+        exit(EXIT_FAILURE);
+    }
+
+    alarm_serial = 1;
+    alarm_queue  = NULL;
+}
+
+/*
+=head1 Parrot_alarm_set(FLOATVAL when)
+
+A helper function to set an alarm.
+
+=cut
+*/
+
+static void
+set_posix_alarm(FLOATVAL wait) 
+{
+    const int MIL = 1000000;
+    struct itimerval itmr;
+    int sec, usec;
+
+    sec  = (int) wait;
+    usec = (int) ((wait - sec) * MIL);
+
+    itmr.it_value.tv_sec     = sec;
+    itmr.it_value.tv_usec    = usec;
+    itmr.it_interval.tv_sec  = 0;
+    itmr.it_interval.tv_usec = 0;
+
+    fprintf(stderr, "setitimer(%.02lf): sec = %d; usec = %d\n", wait, sec, usec);
+    
+    if(setitimer(ITIMER_REAL, &itmr, 0) == -1) {
+        perror("setitimer failed in set_posix_alarm");
+        exit(EXIT_FAILURE);
+    }
+}
+
+
+/*
+=head1 Parrot_alarm_callback()
+
+Callback for SIGALRM. When this is called, a timer should be ready to fire.
+
+=cut
+*/
+
+void
+Parrot_alarm_callback(SHIM(int sig_number))
+{
+    FLOATVAL now, wait;
+    Parrot_alarm_queue* qp;
+
+    fprintf(stderr, "Got Parrot_timers_alarm_callback()\n");
+
+    /* Not atomic; only one thread ever writes this value */
+    alarm_serial += 1;
+
+    // Find the first future item.
+    now = Parrot_floatval_time();
+    while(alarm_queue != NULL && alarm_queue->when < now) {
+        qp = alarm_queue->next;
+        free(alarm_queue);
+        alarm_queue = qp;
+    }
+
+    if(alarm_queue != NULL && alarm_queue->alarm_set == 0) {
+        wait = alarm_queue->when - now;
+        set_posix_alarm(wait);
+        qp->alarm_set = 1;
+    }
+}
+
+/*
+=head1 Parrot_alarm_check(Parrot_alarm_state*)
+
+Has any alarm triggered since we last checked?
+
+Possible design improvement: Alert only the thread that
+set the alarm.
+
+=cut
+*/
+
+PARROT_EXPORT
+int
+Parrot_alarm_check(Parrot_alarm_state* last_serial)
+{
+    if(*last_serial == alarm_serial) {
+        return 0;
+    } else {
+        *last_serial = alarm_serial;
+        return 1;
+    }
+}
+
+/*
+=head1 Parrot_alarm_set(FLOATVAL when)
+
+Sets an alarm to trigger at time 'when'.
+
+=cut
+*/
+
+PARROT_EXPORT
+void
+Parrot_alarm_set(FLOATVAL when) {
+    Parrot_alarm_queue *new_alarm; 
+    Parrot_alarm_queue **qpp;
+    FLOATVAL now;
+
+    /* Better late than early */
+    when += 0.0001;
+
+    now = Parrot_floatval_time();
+
+    new_alarm = (Parrot_alarm_queue*) malloc(sizeof(Parrot_alarm_queue));
+    new_alarm->when = when;
+
+    if(alarm_queue == NULL || when < alarm_queue->when) {
+        new_alarm->next = alarm_queue;
+        new_alarm->alarm_set = 1;
+        alarm_queue = new_alarm;
+        set_posix_alarm(when - now);
+        return;
+    }
+
+    qpp = &alarm_queue;
+    while(*qpp != NULL && (*qpp)->when < when) {
+        qpp = &(alarm_queue->next);
+    }
+
+    new_alarm->next = *qpp;
+    new_alarm->alarm_set = 0;
+    *qpp = new_alarm;
+}
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Modified: branches/gsoc_threads/src/main.c
==============================================================================
--- branches/gsoc_threads/src/main.c	Tue Jun 22 17:37:26 2010	(r47763)
+++ branches/gsoc_threads/src/main.c	Tue Jun 22 18:14:50 2010	(r47764)
@@ -25,6 +25,7 @@
 #include "parrot/imcc.h"
 #include "parrot/longopt.h"
 #include "parrot/runcore_api.h"
+#include "parrot/alarm.h"
 #include "pmc/pmc_callcontext.h"
 
 /* For gc_sys_type_enum */
@@ -136,6 +137,9 @@
     /* Now initialize interpreter */
     initialize_interpreter(interp, (void*)&stacktop);
 
+    /* Register signal handler for timers */
+    Parrot_alarm_init();
+
     /* Parse flags */
     sourcefile = parseflags(interp, argc, argv, &pir_argc, &pir_argv, &core, &trace);
 

Added: branches/gsoc_threads/src/pmc/alarmtest.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_threads/src/pmc/alarmtest.pmc	Tue Jun 22 18:14:50 2010	(r47764)
@@ -0,0 +1,62 @@
+
+#include "parrot/alarm.h"
+
+/* HEADERIZER HFILE: none */
+/* HEADERIZER BEGIN: static */
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
+
+/* blah */
+
+/* HEADERIZER END: static */
+
+pmclass AlarmTest auto_attrs {
+    ATTR INTVAL id;
+    ATTR INTVAL n;
+    ATTR FLOATVAL set;
+
+    VTABLE void init() {
+        fprintf(stderr, "Made an AlarmTest\n");
+    }
+
+    VTABLE STRING *get_string() {
+        char blah[] = "blah";
+        return Parrot_str_new(interp, blah, strlen(blah));
+    }
+
+    METHOD wonk() {
+        fprintf(stderr, "Wonk\n");
+    }
+
+    METHOD set_alarm(FLOATVAL t) {
+        FLOATVAL now, when;
+        Parrot_AlarmTest_attributes* attrs;
+
+        now  = Parrot_floatval_time();
+        when = now + t;
+        Parrot_alarm_set(when);
+
+        attrs = PMC_data_typed(SELF, Parrot_AlarmTest_attributes *);
+        attrs->set = when;
+
+        fprintf(stderr, "At %.06lf set alarm for %.06lf\n", now, when);
+    }
+
+    METHOD check_alarm() {
+        FLOATVAL now;
+        Parrot_AlarmTest_attributes* attrs;
+        INTVAL changed = 0;
+
+        attrs = PMC_data_typed(SELF, Parrot_AlarmTest_attributes *);
+
+        if(Parrot_alarm_check(&(attrs->n))) {
+            now = Parrot_floatval_time();
+
+            fprintf(stderr, "At %.06lf maybe alarm.\n", now);
+
+            if(now > attrs->set)
+                changed = 1;
+        }
+
+        RETURN(INTVAL changed);
+    }
+}

Added: branches/gsoc_threads/src/pmc/pmclist.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_threads/src/pmc/pmclist.pmc	Tue Jun 22 18:14:50 2010	(r47764)
@@ -0,0 +1,481 @@
+/*
+Copyright (C) 2001-2010, Parrot Foundation.
+$Id: resizablepmcarray.pmc 47545 2010-06-10 21:09:12Z Chandon $
+
+=head1 NAME
+
+src/pmc/pmclist.pmc - List of PMCs
+
+=head1 DESCRIPTION
+
+A doubly linked list of PMCs, for when push, pop, shift, and unshift
+all want to be O(1).
+
+=head2 Vtable Functions
+
+=over 4
+
+=cut
+
+*/
+
+/* HEADERIZER HFILE: pmc_pmclist.h */
+/* HEADERIZER BEGIN: blah */
+
+/* blah */
+
+/* HEADERIZER END: blah */
+
+/* HEADERIZER HFILE: none */
+/* HEADERIZER BEGIN: static */
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
+
+PARROT_DOES_NOT_RETURN
+static void throw_pop_empty(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+PARROT_DOES_NOT_RETURN
+static void throw_shift_empty(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+#define ASSERT_ARGS_throw_pop_empty __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
+#define ASSERT_ARGS_throw_shift_empty __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
+/* HEADERIZER END: static */
+
+/* It's a doubly linked list */
+typedef struct PMC_List_Item {
+    PMC *data;
+    struct PMC_List_Item *prev;
+    struct PMC_List_Item *next;
+} PMC_List_Item;
+
+pmclass PMCList auto_attrs {
+    ATTR void *head;
+    ATTR void *foot;
+    ATTR INTVAL size;
+
+/*
+=item C<void init()>
+
+Initializes the list.
+
+=cut
+*/
+
+    VTABLE void init() {
+        PObj_custom_mark_SET(SELF);
+        PObj_custom_destroy_SET(SELF);
+
+        SET_ATTR_head(INTERP, SELF, NULL);
+        SET_ATTR_foot(INTERP, SELF, NULL);
+        SET_ATTR_size(INTERP, SELF, 0);
+    }
+
+/*
+=item C<void destroy()>
+
+Free all the list cells.
+
+=cut
+*/
+
+    VTABLE void destroy() {
+        void *tmp;
+        PMC_List_Item *aa;
+        PMC_List_Item *bb;
+
+        GET_ATTR_head(INTERP, SELF, tmp);
+        aa = (PMC_List_Item*) tmp;
+
+        while(aa != NULL) {
+            bb = aa;
+            aa = aa->next;
+            free(bb);
+        }
+    }
+
+/*
+=item C<INTVAL get_integer()>
+
+Returns the size of the list.
+
+=cut
+*/
+    
+    VTABLE INTVAL get_integer() {
+        INTVAL size;
+        GET_ATTR_size(INTERP, SELF, size);
+        return size;
+    }
+
+/*
+=item C<PMC *shift_pmc()>
+
+Removes and returns an item from the start of the array.
+
+=cut
+*/
+
+    VTABLE PMC *shift_pmc() {
+        INTVAL size;
+        void *tmp;
+        PMC_List_Item *head;
+        PMC_List_Item *next;
+        PMC_List_Item *item;
+        PMC *data;
+
+        GET_ATTR_size(INTERP, SELF, size);
+
+        if (0 >= size)
+            throw_shift_empty(INTERP);
+
+        GET_ATTR_head(INTERP, SELF, tmp);
+        item = (PMC_List_Item*) tmp;
+        data = item->data;
+
+        size -= 1;
+        SET_ATTR_size(INTERP, SELF, size);
+
+        head = item->next;
+        SET_ATTR_head(INTERP, SELF, head);
+
+        if(head == NULL) {
+            /* size == 0 */
+            SET_ATTR_foot(INTERP, SELF, NULL);
+        } else {
+            head->prev = NULL;
+        }
+        
+        if(size == 1) {
+            head->next = NULL;
+            SET_ATTR_foot(INTERP, SELF, head);
+        }
+
+        free(item);
+
+        return data;
+    }
+
+/*
+=item C<void push_pmc(PMC *value)>
+
+Extends the array by adding an element of value C<*value> to the end of
+the array.
+
+=cut
+
+*/
+
+    VTABLE void push_pmc(PMC *value) {
+        INTVAL size;
+        void *tmp;
+        PMC_List_Item *foot;
+        PMC_List_Item *item;
+
+        GET_ATTR_size(INTERP, SELF, size);
+        GET_ATTR_foot(INTERP, SELF, tmp);
+        foot = (PMC_List_Item*) tmp;
+
+        item = (PMC_List_Item*) malloc(sizeof(PMC_List_Item));
+        item->next = NULL;
+        item->prev = foot;
+        item->data = value;
+
+        if(foot)
+            foot->next = item;
+
+        size += 1;
+        
+        SET_ATTR_foot(INTERP, SELF, item);
+        SET_ATTR_size(INTERP, SELF, size);
+
+        if(size == 1)
+            SET_ATTR_head(INTERP, SELF, item);
+
+        return;
+    }
+
+/*
+=item C<PMC *pop_pmc()>
+
+Removes and returns the last element in the array.
+
+=cut
+*/
+
+    VTABLE PMC *pop_pmc() {
+        INTVAL size;
+        void *tmp;
+        PMC_List_Item *foot;
+        PMC_List_Item *item;
+        PMC *data;
+
+        GET_ATTR_size(INTERP, SELF, size);
+
+        if (0 >= size)
+            throw_pop_empty(INTERP);
+
+        GET_ATTR_foot(INTERP, SELF, tmp);
+        item = (PMC_List_Item*) tmp;
+        data = item->data;
+
+        size -= 1;
+        SET_ATTR_size(INTERP, SELF, size);
+
+        foot = item->prev;
+        SET_ATTR_foot(INTERP, SELF, foot);
+
+        if(foot == NULL) {
+            /* size == 0 */
+            SET_ATTR_head(INTERP, SELF, NULL);
+        } else {
+            foot->next = NULL;
+        }
+        
+        if(size == 1) {
+            foot->prev = NULL;
+            SET_ATTR_head(INTERP, SELF, foot);
+        }
+
+        free(item);
+
+        return data;
+    }
+
+/*
+
+=item C<void unshift_pmc(PMC *value)>
+
+Extends the array by adding an element of value C<*value> to the begin of
+the array.
+
+=cut
+
+*/
+
+    VTABLE void unshift_pmc(PMC *value) {
+        INTVAL size;
+        void *tmp;
+        PMC_List_Item *head;
+        PMC_List_Item *item;
+
+        GET_ATTR_size(INTERP, SELF, size);
+        GET_ATTR_head(INTERP, SELF, tmp);
+        head = (PMC_List_Item*) tmp;
+
+        item = (PMC_List_Item*) malloc(sizeof(PMC_List_Item));
+        item->prev = NULL;
+        item->next = head;
+        item->data = value;
+
+        if(head)
+            head->prev = item;
+
+        size += 1;
+        
+        SET_ATTR_head(INTERP, SELF, item);
+        SET_ATTR_size(INTERP, SELF, size);
+
+        if(size == 1)
+            SET_ATTR_foot(INTERP, SELF, item);
+
+        return;
+    }
+
+/*
+
+=item C<PMC *clone()>
+
+Creates and returns a copy of the list.
+
+=cut
+
+*/
+
+    VTABLE PMC *clone() {
+        PMC *copy = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
+        void* tmp;
+        PMC_List_Item *it;
+
+        GET_ATTR_head(INTERP, SELF, tmp);
+        it = (PMC_List_Item*) tmp;
+
+        while(it != NULL) {
+            VTABLE_push_pmc(INTERP, copy, it->data);
+            it = it->next;
+        }
+        
+        return copy;
+    }
+
+/*
+
+=item C<STRING *get_repr()>
+
+Returns the Parrot string representation C<ResizablePMCArray>.
+
+=cut
+
+*/
+
+    VTABLE STRING *get_repr() {
+        PMC_List_Item *it;
+        void* tmp;
+        STRING *res = CONST_STRING(INTERP, "[ ");
+
+        GET_ATTR_head(INTERP, SELF, tmp);
+        it = (PMC_List_Item*) tmp;
+
+        while(it != NULL) {
+            res = Parrot_str_concat(INTERP, res, VTABLE_get_repr(INTERP, it->data));
+            it = it->next;
+        }
+
+        return Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, " ]"));
+    }
+
+
+/*
+
+=item C<void visit(PMC *info)>
+
+This is used by freeze/thaw to visit the contents of the array.
+
+C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
+
+=item C<void freeze(PMC *info)>
+
+Used to archive the array.
+
+=item C<void thaw(PMC *info)>
+
+Used to unarchive the array.
+
+=cut
+
+*/
+
+    VTABLE void visit(PMC *info) {
+        PMC_List_Item *it;
+
+        GET_ATTR_head(INTERP, SELF, it);
+        while(it != NULL) {
+            VISIT_PMC(INTERP, info, it->data);
+            it = it->next;
+        }
+
+        SUPER(info);
+    }
+
+    VTABLE void freeze(PMC *info) {
+        SUPER(info);
+        VTABLE_push_integer(INTERP, info, VTABLE_elements(INTERP, SELF));
+    }
+
+    VTABLE void thaw(PMC *info) {
+        SUPER(info);
+        SELF.set_integer_native(VTABLE_shift_integer(INTERP, info));
+    }
+
+/*
+
+=item METHOD PMC* shift()
+
+=item METHOD PMC* pop()
+
+Method forms to remove and return a PMC from the beginning or
+end of the array.
+
+=cut
+
+*/
+
+    METHOD shift() {
+        PMC * const value = VTABLE_shift_pmc(INTERP, SELF);
+        RETURN(PMC *value);
+    }
+
+    METHOD pop() {
+        PMC * const value = VTABLE_pop_pmc(INTERP, SELF);
+        RETURN(PMC *value);
+    }
+
+/*
+
+=item METHOD unshift(PMC* value)
+
+=item METHOD push(PMC* value)
+
+Method forms to add a PMC to the beginning or end of the array.
+
+=cut
+
+*/
+
+    METHOD unshift(PMC* value) {
+        VTABLE_unshift_pmc(INTERP, SELF, value);
+    }
+
+    METHOD push(PMC* value) {
+        VTABLE_push_pmc(INTERP, SELF, value);
+    }
+
+}
+
+/*
+
+=back
+
+=head2 Auxiliar functions
+
+=over 4
+
+=item C<static void throw_shift_empty(PARROT_INTERP)>
+
+=item C<static void throw_pop_empty(PARROT_INTERP)>
+
+Throws with the appropiate message.
+
+=cut
+
+*/
+
+PARROT_DOES_NOT_RETURN
+static void
+throw_shift_empty(PARROT_INTERP)
+{
+    ASSERT_ARGS(throw_shift_empty)
+    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
+            "PMCList: Can't shift from an empty array!");
+}
+
+PARROT_DOES_NOT_RETURN
+static void
+throw_pop_empty(PARROT_INTERP)
+{
+    ASSERT_ARGS(throw_pop_empty)
+    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
+            "PMCList: Can't pop from an empty array!");
+}
+
+/*
+
+=back
+
+=head1 See also
+
+F<docs/pdds/pdd17_basic_types.pod>.
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Modified: branches/gsoc_threads/src/pmc/scheduler.pmc
==============================================================================
--- branches/gsoc_threads/src/pmc/scheduler.pmc	Tue Jun 22 17:37:26 2010	(r47763)
+++ branches/gsoc_threads/src/pmc/scheduler.pmc	Tue Jun 22 18:14:50 2010	(r47764)
@@ -454,6 +454,8 @@
         STRING * const iter_str    = CONST_STRING(INTERP, "handler_iter");
         PMC    *iter;
 
+        fprintf(stderr, "Derf\n");
+
         /* Exceptions store the handler iterator for rethrow, other kinds of
          * tasks don't (though they could). */
         if (task->vtable->base_type == enum_class_Exception

Modified: branches/gsoc_threads/src/scheduler.c
==============================================================================
--- branches/gsoc_threads/src/scheduler.c	Tue Jun 22 17:37:26 2010	(r47763)
+++ branches/gsoc_threads/src/scheduler.c	Tue Jun 22 18:14:50 2010	(r47764)
@@ -70,12 +70,21 @@
 
 */
 
+static int interp_count = 0;
+
 void
 Parrot_cx_init_scheduler(PARROT_INTERP)
 {
 
     ASSERT_ARGS(Parrot_cx_init_scheduler)
 
+/*
+    if(interp_count++ > 1) {
+       fprintf(stderr, "More than one interp?\n");
+        exit(0);
+    }
+*/
+
     if (!interp->parent_interpreter) {
         PMC *scheduler;
 

Added: branches/gsoc_threads/t/pmc/pmclist.t
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_threads/t/pmc/pmclist.t	Tue Jun 22 18:14:50 2010	(r47764)
@@ -0,0 +1,185 @@
+#!./parrot
+# Copyright (C) 2001-2009, Parrot Foundation.
+# $Id$
+
+.sub main :main
+    .include 'test_more.pir'
+
+    plan(9)
+
+    empty_exceptions()
+    push_five()
+    push_two_pop_two()
+    unshift_two_shift_two()
+    push_shift()
+    unshift_pop()
+.end
+
+.sub empty_exceptions
+    $P0 = new 'PMCList'
+
+    push_eh pop_good
+    $P1 = pop $P0
+    pop_eh
+
+    ok(0, "pop empty")
+    goto try_shift
+    
+pop_good:
+    ok(1, "pop empty")
+
+try_shift:
+
+    $P0 = new 'PMCList'
+    
+    push_eh shift_good
+    $P1 = pop $P0
+    pop_eh
+
+    ok(0, "shift empty")
+    .return()
+
+shift_good:
+    ok(1, "shift empty")
+.end
+
+.sub push_many
+    .param pmc a
+    .param int n
+
+    if n < 1 goto done
+    
+    $P0 = new 'Integer'
+    $P0 = n
+    push a, $P0
+
+    $N0 = n - 1
+    push_many(a, $N0)
+
+done:
+    .return()
+.end
+
+.sub push_five
+    $P0 = new 'PMCList'
+
+    push_eh fail
+    push_many($P0, 5)
+    pop_eh
+
+    $I0 = $P0
+    
+    if $I0 != 5 goto fail
+    ok(1, "push five")
+
+    .return()
+
+fail:
+    ok(0, "push five")
+.end
+
+.sub push_two_pop_two
+    $P0 = new 'PMCList'
+
+    push_many($P0, 2)
+
+    $P1 = pop $P0
+    $I0 = $P0
+
+    if $I0 == 1 goto size_good
+    
+    ok(0, "push two pop one")
+    goto try_value
+    
+size_good:
+    ok(1, "push two pop one")
+
+try_value:
+    $P1 = pop $P0
+    $I0 = $P1
+
+    if $I0 == 2 goto value_good
+    ok(0, "push two pop two")
+    .return()
+    
+value_good:     
+    ok(1, "push two pop two")
+.end
+
+.sub unshift_two_shift_two
+    $P0 = new 'PMCList'
+
+    $P1 = new 'Integer', 2
+    unshift $P0, $P1
+
+    $P1 = new 'Integer', 1
+    unshift $P0, $P1
+    
+    $P1 = shift $P0
+    $I0 = $P0
+
+    if $I0 == 1 goto size_good
+    
+    ok(0, "unshift shift size")
+    goto try_value
+    
+size_good:
+    ok(1, "unshift shift size")
+
+try_value:
+    $P1 = shift $P0
+    $I0 = $P1
+
+    if $I0 == 2 goto value_good
+    ok(0, "unshift shift value")
+    .return()
+    
+value_good:     
+    ok(1, "unshift shift value")
+.end
+
+.sub push_shift
+    $P0 = new 'PMCList'
+
+    $P1 = new 'Integer', 5
+    push $P0, $P1
+
+    $P1 = new 'Integer', 6
+    push $P0, $P1
+
+    $P1 = shift $P0
+    $I0 = $P1
+
+    if $I0 == 5 goto value_good
+    ok(0, "push shift")
+    .return()
+    
+value_good:
+    ok(1, "push shift")
+.end
+
+.sub unshift_pop
+    $P0 = new 'PMCList'
+
+    $P1 = new 'Integer', 5
+    unshift $P0, $P1
+
+    $P1 = new 'Integer', 6
+    unshift $P0, $P1
+
+    $P1 = pop $P0
+    $I0 = $P1
+
+    if $I0 == 5 goto value_good
+    ok(0, "unshift pop")
+    .return()
+    
+value_good:
+    ok(1, "unshift pop")
+.end
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:


More information about the parrot-commits mailing list