cvsuser 03/12/16 03:33:18
Modified: . MANIFEST
dynoplibs alarm.pasm myops.ops
config/init/hints linux.pl
docs/dev events.pod
include/parrot thr_pthread.h thread.h tsq.h
src events.c tsq.c
Added: dynoplibs alarm2.pasm
Log:
event-handling-8
* thread creation macros
* must now link with pthread lib - no test anymore
this could break platforms that have pthread but dont link with it
* insert multiple timer events according to abs_time
* handle repeated timer events
Revision Changes Path
1.516 +1 -0 parrot/MANIFEST
Index: MANIFEST
===================================================================
RCS file: /cvs/public/parrot/MANIFEST,v
retrieving revision 1.515
retrieving revision 1.516
diff -u -w -r1.515 -r1.516
--- MANIFEST 15 Dec 2003 15:12:36 -0000 1.515
+++ MANIFEST 16 Dec 2003 11:33:04 -0000 1.516
@@ -237,6 +237,7 @@
dynclasses/subproxy.pmc [devel]
dynoplibs/README [devel]
dynoplibs/alarm.pasm [devel]
+dynoplibs/alarm2.pasm [devel]
dynoplibs/myops.ops [devel]
dynoplibs/test.pasm [devel]
editor/Makefile [devel]
1.2 +5 -4 parrot/dynoplibs/alarm.pasm
Index: alarm.pasm
===================================================================
RCS file: /cvs/public/parrot/dynoplibs/alarm.pasm,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -w -r1.1 -r1.2
--- alarm.pasm 15 Dec 2003 15:12:42 -0000 1.1
+++ alarm.pasm 16 Dec 2003 11:33:07 -0000 1.2
@@ -3,16 +3,17 @@
loadlib P1, "myops_ops"
find_global P0, "_alarm"
- alarm 2.5, P0
- null I0
+ alarm 3.5, P0
+ set I0, 1
loop:
sleep 1
print I0
print "\n"
inc I0
# check_events
- branch loop
+ le I0, 5, loop
+ print "done.\n"
end
.pcc_sub _alarm:
print "alarm\n"
- exit 0
+ invoke P1
1.4 +9 -0 parrot/dynoplibs/myops.ops
Index: myops.ops
===================================================================
RCS file: /cvs/public/parrot/dynoplibs/myops.ops,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -w -r1.3 -r1.4
--- myops.ops 15 Dec 2003 15:12:42 -0000 1.3
+++ myops.ops 16 Dec 2003 11:33:07 -0000 1.4
@@ -47,10 +47,19 @@
Call alarm handler sub $2 after $1 time has elapsed.
+=item B<alarm>(in NUM, in NUM, in PMC)
+
+Call alarm handler sub $3 after $1 time has elapsed, repeat after $2.
+
=cut
op alarm(in NUM, in PMC) {
Parrot_new_timer_event(interpreter, $1, 0.0, $2);
+ goto NEXT();
+}
+
+op alarm(in NUM, in NUM, in PMC) {
+ Parrot_new_timer_event(interpreter, $1, $2, $3);
goto NEXT();
}
1.1 parrot/dynoplibs/alarm2.pasm
Index: alarm2.pasm
===================================================================
# test program vor event handling
# -b, -g, -S run cores only by now
loadlib P1, "myops_ops"
find_global P0, "_alarm3"
alarm 3.3, 0.4, P0
find_global P0, "_alarm2"
alarm 2.2, P0
find_global P0, "_alarm"
alarm 1.5, 2.0, P0
set I0, 1
loop:
sleep 1
print I0
print "\n"
inc I0
le I0, 5, loop
print "done.\n"
end
.pcc_sub _alarm:
print "alarm\n"
invoke P1
.pcc_sub _alarm2:
print "alarm2\n"
invoke P1
.pcc_sub _alarm3:
print "alarm3\n"
invoke P1
1.3 +1 -1 parrot/config/init/hints/linux.pl
Index: linux.pl
===================================================================
RCS file: /cvs/public/parrot/config/init/hints/linux.pl,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -w -r1.2 -r1.3
--- linux.pl 15 Dec 2003 15:12:46 -0000 1.2
+++ linux.pl 16 Dec 2003 11:33:09 -0000 1.3
@@ -1,6 +1,6 @@
my $libs = Configure::Data->get('libs');
if ($libs !~ /-lpthread/) {
- $libs .= ' -pthread';
+ $libs .= ' -lpthread';
}
Configure::Data->set(
1.2 +0 -2 parrot/docs/dev/events.pod
Index: events.pod
===================================================================
RCS file: /cvs/public/parrot/docs/dev/events.pod,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -w -r1.1 -r1.2
--- events.pod 15 Dec 2003 15:12:40 -0000 1.1
+++ events.pod 16 Dec 2003 11:33:11 -0000 1.2
@@ -78,8 +78,6 @@
=item Insert timed events accoring to their abstime
-=item Reinsert repeated events
-
=item Synchronous event API
Sync events could be placed directly into the interpreters task queue.
1.3 +16 -1 parrot/include/parrot/thr_pthread.h
Index: thr_pthread.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/thr_pthread.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -w -r1.2 -r1.3
--- thr_pthread.h 15 Dec 2003 15:12:57 -0000 1.2
+++ thr_pthread.h 16 Dec 2003 11:33:16 -0000 1.3
@@ -1,7 +1,7 @@
/* thr_pthread.h
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: thr_pthread.h,v 1.2 2003/12/15 15:12:57 leo Exp $
+ * $Id: thr_pthread.h,v 1.3 2003/12/16 11:33:16 leo Exp $
* Overview:
* POSIS pthread interface
* Data Structure and Algorithms:
@@ -35,8 +35,23 @@
# define COND_INIT(c) pthread_cond_init(&c, NULL);
# define COND_DESTROY(c) pthread_cond_destroy(&c)
+# define THREAD_CREATE_DETACHED(t, func, arg) do { \
+ pthread_attr_t attr; \
+ int rc = pthread_attr_init(&attr); \
+ assert(rc == 0); \
+ rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); \
+ assert(rc == 0); \
+ rc = pthread_create(&t, &attr, func, arg); \
+ assert(rc == 0); \
+ pthread_attr_destroy(&attr); \
+ } while (0)
+
+# define THREAD_CREATE_JOINABLE(t, func, arg) \
+ pthread_create(&t, NULL, func, arg)
+
typedef pthread_mutex_t Parrot_mutex;
typedef pthread_cond_t Parrot_cond;
+typedef pthread_t Parrot_thread;
#endif
1.9 +5 -1 parrot/include/parrot/thread.h
Index: thread.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/thread.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -w -r1.8 -r1.9
--- thread.h 15 Dec 2003 15:12:57 -0000 1.8
+++ thread.h 16 Dec 2003 11:33:16 -0000 1.9
@@ -1,7 +1,7 @@
/* thread.h
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: thread.h,v 1.8 2003/12/15 15:12:57 leo Exp $
+ * $Id: thread.h,v 1.9 2003/12/16 11:33:16 leo Exp $
* Overview:
* This is the api header for the thread primitives
* Data Structure and Algorithms:
@@ -30,8 +30,12 @@
# define COND_INIT(c)
# define COND_DESTROY(c)
+# define THREAD_CREATE_DETACHED(t, func, arg)
+# define THREAD_CREATE_JOINABLE(t, func, arg)
+
# define Parrot_mutex int
# define Parrot_cond int
+# define Parrot_thread int
# ifndef _STRUCT_TIMESPEC
# define _STRUCT_TIMESPEC
1.8 +3 -1 parrot/include/parrot/tsq.h
Index: tsq.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/tsq.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -w -r1.7 -r1.8
--- tsq.h 15 Dec 2003 15:12:57 -0000 1.7
+++ tsq.h 16 Dec 2003 11:33:16 -0000 1.8
@@ -1,7 +1,7 @@
/* tsq.h
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: tsq.h,v 1.7 2003/12/15 15:12:57 leo Exp $
+ * $Id: tsq.h,v 1.8 2003/12/16 11:33:16 leo Exp $
* Overview:
* Defines the thread-safe queue system
* Data Structure and Algorithms:
@@ -45,6 +45,8 @@
PARROT_INLINE QUEUE_ENTRY *peek_entry(QUEUE *);
QUEUE_ENTRY *wait_for_entry(QUEUE *);
void push_entry(QUEUE *, QUEUE_ENTRY *);
+void nosync_insert_entry(QUEUE *, QUEUE_ENTRY *);
+void insert_entry(QUEUE *, QUEUE_ENTRY *);
void queue_lock(QUEUE *);
void queue_unlock(QUEUE *);
void queue_signal(QUEUE *);
1.10 +34 -29 parrot/src/events.c
Index: events.c
===================================================================
RCS file: /cvs/public/parrot/src/events.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -w -r1.9 -r1.10
--- events.c 15 Dec 2003 15:42:31 -0000 1.9
+++ events.c 16 Dec 2003 11:33:17 -0000 1.10
@@ -1,7 +1,7 @@
/* events.c
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: events.c,v 1.9 2003/12/15 15:42:31 leo Exp $
+ * $Id: events.c,v 1.10 2003/12/16 11:33:17 leo Exp $
* Overview:
* Event handling stuff
* Data Structure and Algorithms:
@@ -70,11 +70,7 @@
static void
init_events_first(Parrot_Interp interpreter)
{
-#if defined(PARROT_HAS_HEADER_PTHREAD) && defined(PARROT_HAS_HEADER_LIB_PTHREAD)
- pthread_attr_t attr;
- static pthread_t the_thread;
- int rc;
-#endif
+ Parrot_thread the_thread;
/*
* init event queue - be sure its done only once
* we could use pthread_once for queue_init
@@ -84,23 +80,7 @@
/*
* we start an event_handler thread
*/
-#if defined(PARROT_HAS_HEADER_PTHREAD) && defined(PARROT_HAS_HEADER_LIB_PTHREAD)
- /* TODO use some macros */
-
- /* init thread attributes */
- rc = pthread_attr_init(&attr);
- assert(rc == 0);
- /* we want a detached - non joinable thread */
- rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- assert(rc == 0);
-
- /* now create the task thread */
- rc = pthread_create(&the_thread, &attr, event_thread, event_queue);
- assert(rc == 0);
-
- /* destroy the thread attribute structure */
- pthread_attr_destroy(&attr);
-#endif
+ THREAD_CREATE_DETACHED(the_thread, event_thread, event_queue);
/*
* now set some sig handlers
*/
@@ -139,16 +119,18 @@
{
QUEUE_ENTRY* entry = mem_sys_allocate(sizeof(QUEUE_ENTRY));
entry->next = NULL;
+ ev->interp = interpreter;
+ entry->data = ev;
switch (ev->type) {
case EVENT_TYPE_TIMER:
entry->type = QUEUE_ENTRY_TYPE_TIMED_EVENT;
+ insert_entry(event_queue, entry);
break;
default:
entry->type = QUEUE_ENTRY_TYPE_EVENT;
- }
- ev->interp = interpreter;
- entry->data = ev;
push_entry(event_queue, entry);
+ break;
+ }
}
/*
@@ -177,6 +159,24 @@
}
/*
+ * duplicate timed entry and add interval to abstime
+ */
+static QUEUE_ENTRY*
+dup_entry_interval(QUEUE_ENTRY* entry, FLOATVAL now)
+{
+ parrot_event *event;
+ QUEUE_ENTRY *new_entry;
+
+ new_entry = mem_sys_allocate(sizeof(QUEUE_ENTRY));
+ new_entry->next = NULL;
+ new_entry->type = entry->type;
+ new_entry->data = mem_sys_allocate(sizeof(parrot_event));
+ mem_sys_memcopy(new_entry->data, entry->data, sizeof(parrot_event));
+ event = new_entry->data;
+ 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.
*/
@@ -227,14 +227,19 @@
now = Parrot_floatval_time();
/*
* if the timer_event isn't due yet, ignore the event
- * (we where signalled on insert of the event)
+ * (we were signalled on insert of the event)
* wait until we get at it again when time has elapsed
*/
if (now < event->u.timer_event.abs_time)
goto again;
entry = nosync_pop_entry(event_q);
- /* TODO if event is repeated dup and reinsert it
+ /*
+ * if event is repeated dup and reinsert it
*/
+ if (event->u.timer_event.interval) {
+ nosync_insert_entry(event_q,
+ dup_entry_interval(entry, now));
+ }
break;
default:
internal_exception(1, "Unknown queue entry");
1.10 +54 -1 parrot/src/tsq.c
Index: tsq.c
===================================================================
RCS file: /cvs/public/parrot/src/tsq.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -w -r1.9 -r1.10
--- tsq.c 15 Dec 2003 15:13:05 -0000 1.9
+++ tsq.c 16 Dec 2003 11:33:17 -0000 1.10
@@ -1,7 +1,7 @@
/* tsq.c
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: tsq.c,v 1.9 2003/12/15 15:13:05 leo Exp $
+ * $Id: tsq.c,v 1.10 2003/12/16 11:33:17 leo Exp $
* Overview:
* Thread-safe queues
* Data Structure and Algorithms:
@@ -11,6 +11,7 @@
*/
#include "parrot/parrot.h"
+#include <assert.h>
/* A synchronized entry popper */
QUEUE_ENTRY *
@@ -77,6 +78,58 @@
queue->tail = entry;
}
queue_signal(queue);
+ queue_unlock(queue);
+}
+
+/*
+ * insert a timed event according to abstime
+ * caller has to hold the queue mutex
+ */
+void
+nosync_insert_entry(QUEUE *queue, QUEUE_ENTRY *entry)
+{
+ QUEUE_ENTRY *cur = queue->head, *prev;
+ parrot_event *event, *cur_event;
+ FLOATVAL abs_time;
+
+ assert(entry->type == QUEUE_ENTRY_TYPE_TIMED_EVENT);
+ /*
+ * empty queue - just insert
+ */
+ if (!cur) {
+ queue->head = entry;
+ queue->tail = entry;
+ return;
+ }
+
+ prev = NULL;
+ event = entry->data;
+ abs_time = event->u.timer_event.abs_time;
+ while (cur && cur->type == QUEUE_ENTRY_TYPE_TIMED_EVENT) {
+ cur_event = cur->data;
+ if (abs_time > cur_event->u.timer_event.abs_time) {
+ prev = cur;
+ cur = cur->next;
+ }
+ else
+ break;
+ }
+ if (!prev)
+ queue->head = entry;
+ else {
+ prev->next = entry;
+ if (prev == queue->tail)
+ queue->tail = entry;
+ }
+ entry->next = cur;
+ queue_signal(queue);
+}
+
+void
+insert_entry(QUEUE *queue, QUEUE_ENTRY *entry)
+{
+ queue_lock(queue);
+ nosync_insert_entry(queue, entry);
queue_unlock(queue);
}