[svn:parrot] r48117 - in branches/gsoc_threads: include/parrot include/parrot/oplib src src/ops src/pmc t/pmc
Chandon at svn.parrot.org
Chandon at svn.parrot.org
Tue Jul 20 01:19:43 UTC 2010
Author: Chandon
Date: Tue Jul 20 01:19:43 2010
New Revision: 48117
URL: https://trac.parrot.org/parrot/changeset/48117
Log:
[gsoc_threads] First half of the Task API.
Modified:
branches/gsoc_threads/include/parrot/oplib/core_ops.h
branches/gsoc_threads/include/parrot/oplib/ops.h
branches/gsoc_threads/include/parrot/opsenum.h
branches/gsoc_threads/include/parrot/scheduler.h
branches/gsoc_threads/include/parrot/scheduler_private.h
branches/gsoc_threads/src/events.c
branches/gsoc_threads/src/ops/core.ops
branches/gsoc_threads/src/ops/core_ops.c
branches/gsoc_threads/src/ops/experimental.ops
branches/gsoc_threads/src/pmc/event.pmc
branches/gsoc_threads/src/pmc/task.pmc
branches/gsoc_threads/src/scheduler.c
branches/gsoc_threads/t/pmc/task.t
Modified: branches/gsoc_threads/include/parrot/oplib/core_ops.h
==============================================================================
--- branches/gsoc_threads/include/parrot/oplib/core_ops.h Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/include/parrot/oplib/core_ops.h Tue Jul 20 01:19:43 2010 (r48117)
@@ -1105,6 +1105,9 @@
opcode_t * Parrot_find_codepoint_i_sc(opcode_t *, PARROT_INTERP);
opcode_t * Parrot_finalize_p(opcode_t *, PARROT_INTERP);
opcode_t * Parrot_finalize_pc(opcode_t *, PARROT_INTERP);
+ opcode_t * Parrot_recv_p(opcode_t *, PARROT_INTERP);
+ opcode_t * Parrot_wait_p(opcode_t *, PARROT_INTERP);
+ opcode_t * Parrot_wait_pc(opcode_t *, PARROT_INTERP);
#endif /* PARROT_OPLIB_CORE_OPS_H_GUARD */
Modified: branches/gsoc_threads/include/parrot/oplib/ops.h
==============================================================================
--- branches/gsoc_threads/include/parrot/oplib/ops.h Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/include/parrot/oplib/ops.h Tue Jul 20 01:19:43 2010 (r48117)
@@ -1099,7 +1099,10 @@
PARROT_OP_find_codepoint_i_s, /* 1079 */
PARROT_OP_find_codepoint_i_sc, /* 1080 */
PARROT_OP_finalize_p, /* 1081 */
- PARROT_OP_finalize_pc /* 1082 */
+ PARROT_OP_finalize_pc, /* 1082 */
+ PARROT_OP_recv_p, /* 1083 */
+ PARROT_OP_wait_p, /* 1084 */
+ PARROT_OP_wait_pc /* 1085 */
} parrot_opcode_enums;
Modified: branches/gsoc_threads/include/parrot/opsenum.h
==============================================================================
--- branches/gsoc_threads/include/parrot/opsenum.h Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/include/parrot/opsenum.h Tue Jul 20 01:19:43 2010 (r48117)
@@ -1099,6 +1099,9 @@
enum_ops_find_codepoint_i_sc = 1080,
enum_ops_finalize_p = 1081,
enum_ops_finalize_pc = 1082,
+ enum_ops_recv_p = 1083,
+ enum_ops_wait_p = 1084,
+ enum_ops_wait_pc = 1085,
};
Modified: branches/gsoc_threads/include/parrot/scheduler.h
==============================================================================
--- branches/gsoc_threads/include/parrot/scheduler.h Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/include/parrot/scheduler.h Tue Jul 20 01:19:43 2010 (r48117)
@@ -128,6 +128,11 @@
__attribute__nonnull__(2)
FUNC_MODIFIES(*scheduler);
+PARROT_CANNOT_RETURN_NULL
+PMC* Parrot_cx_stop_task(PARROT_INTERP, ARGIN(opcode_t *next))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2);
+
#define ASSERT_ARGS_Parrot_cx_begin_execution __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(main) \
@@ -182,9 +187,13 @@
#define ASSERT_ARGS_Parrot_cx_runloop_wake __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(scheduler))
+#define ASSERT_ARGS_Parrot_cx_stop_task __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(next))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: src/scheduler.c */
+
/* Timer PMC interface constants */
/* &gen_from_enum(timer.pasm) */
typedef enum {
Modified: branches/gsoc_threads/include/parrot/scheduler_private.h
==============================================================================
--- branches/gsoc_threads/include/parrot/scheduler_private.h Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/include/parrot/scheduler_private.h Tue Jul 20 01:19:43 2010 (r48117)
@@ -46,9 +46,13 @@
/*
* Task private flags
+ *
+ * in_preempt - This flag is set if the runloop is ending because the current
+ * task has been pre-empted. When the runloop ends because a task
+ * is done, this flag is not set.
*/
typedef enum {
- TASK_terminate_runloop_FLAG = PObj_private0_FLAG
+ TASK_in_preempt_FLAG = PObj_private0_FLAG
} task_flags_enum;
#define TASK_get_FLAGS(o) (PObj_get_FLAGS(o))
@@ -57,9 +61,9 @@
#define TASK_flag_CLEAR(flag, o) (TASK_get_FLAGS(o) &= ~(UINTVAL)(TASK_ ## flag ## _FLAG))
/* Mark a task to terminate the scheduler runloop */
-#define TASK_terminate_runloop_TEST(o) TASK_flag_TEST(terminate_runloop, o)
-#define TASK_terminate_runloop_SET(o) TASK_flag_SET(terminate_runloop, o)
-#define TASK_terminate_runloop_CLEAR(o) TASK_flag_CLEAR(terminate_runloop, o)
+#define TASK_in_preempt_TEST(o) TASK_flag_TEST(in_preempt, o)
+#define TASK_in_preempt_SET(o) TASK_flag_SET(in_preempt, o)
+#define TASK_in_preempt_CLEAR(o) TASK_flag_CLEAR(in_preempt, o)
#endif /* PARROT_SCHEDULER_PRIVATE_H_GUARD */
Modified: branches/gsoc_threads/src/events.c
==============================================================================
--- branches/gsoc_threads/src/events.c Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/src/events.c Tue Jul 20 01:19:43 2010 (r48117)
@@ -58,8 +58,8 @@
/* If the scheduler was flagged to terminate, make sure you process all
* tasks. */
- if (SCHEDULER_terminate_requested_TEST(scheduler))
- Parrot_cx_refresh_task_list(interp, scheduler);
+ /* if (SCHEDULER_terminate_requested_TEST(scheduler))
+ Parrot_cx_refresh_task_list(interp, scheduler); */
} /* end of pending tasks */
#endif
Modified: branches/gsoc_threads/src/ops/core.ops
==============================================================================
--- branches/gsoc_threads/src/ops/core.ops Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/src/ops/core.ops Tue Jul 20 01:19:43 2010 (r48117)
@@ -8,9 +8,11 @@
#include "parrot/dynext.h"
#include "parrot/embed.h"
#include "parrot/runcore_api.h"
+#include "parrot/events.h"
#include "pmc/pmc_continuation.h"
#include "pmc/pmc_parrotlibrary.h"
+
END_OPS_PREAMBLE
=head1 NAME
Modified: branches/gsoc_threads/src/ops/core_ops.c
==============================================================================
--- branches/gsoc_threads/src/ops/core_ops.c Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/src/ops/core_ops.c Tue Jul 20 01:19:43 2010 (r48117)
@@ -33,10 +33,12 @@
#include "parrot/dynext.h"
#include "parrot/embed.h"
#include "parrot/runcore_api.h"
+#include "parrot/events.h"
#include "pmc/pmc_continuation.h"
#include "pmc/pmc_parrotlibrary.h"
+
/* Signed shift operator that is compatible with PMC shifts. This is
* guaranteed to produce the same result as bitwise_left_shift_internal modulo
* word size, ignoring the fact that Parrot integers are always signed. This
@@ -60,15 +62,17 @@
# include <unicode/uchar.h>
#endif
+#include "pmc/pmc_task.h"
+
-INTVAL core_numops = 1084;
+INTVAL core_numops = 1087;
/*
** Op Function Table:
*/
-static op_func_t core_op_func_table[1084] = {
+static op_func_t core_op_func_table[1087] = {
Parrot_end, /* 0 */
Parrot_noop, /* 1 */
Parrot_check_events, /* 2 */
@@ -1152,6 +1156,9 @@
Parrot_find_codepoint_i_sc, /* 1080 */
Parrot_finalize_p, /* 1081 */
Parrot_finalize_pc, /* 1082 */
+ Parrot_recv_p, /* 1083 */
+ Parrot_wait_p, /* 1084 */
+ Parrot_wait_pc, /* 1085 */
NULL /* NULL function pointer */
};
@@ -1162,7 +1169,7 @@
** Op Info Table:
*/
-static op_info_t core_op_info_table[1084] = {
+static op_info_t core_op_info_table[1087] = {
{ /* 0 */
/* type PARROT_INLINE_OP, */
"end",
@@ -14159,6 +14166,42 @@
{ PARROT_ARGDIR_IN },
{ 0 }
},
+ { /* 1083 */
+ /* type PARROT_FUNCTION_OP, */
+ "recv",
+ "recv_p",
+ "Parrot_recv_p",
+ /* "", body */
+ 0,
+ 2,
+ { PARROT_ARG_P },
+ { PARROT_ARGDIR_OUT },
+ { 0 }
+ },
+ { /* 1084 */
+ /* type PARROT_FUNCTION_OP, */
+ "wait",
+ "wait_p",
+ "Parrot_wait_p",
+ /* "", body */
+ 0,
+ 2,
+ { PARROT_ARG_P },
+ { PARROT_ARGDIR_IN },
+ { 0 }
+ },
+ { /* 1085 */
+ /* type PARROT_FUNCTION_OP, */
+ "wait",
+ "wait_pc",
+ "Parrot_wait_pc",
+ /* "", body */
+ 0,
+ 2,
+ { PARROT_ARG_PC },
+ { PARROT_ARGDIR_IN },
+ { 0 }
+ },
};
@@ -25009,6 +25052,50 @@
return (opcode_t *)cur_opcode + 2;}
+opcode_t *
+Parrot_recv_p(opcode_t *cur_opcode, PARROT_INTERP) {
+ const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
+ opcode_t *const dest = cur_opcode + 2;
+ PREG(1) = PMCNULL;
+
+return (opcode_t *)cur_opcode + 2;}
+
+opcode_t *
+Parrot_wait_p(opcode_t *cur_opcode, PARROT_INTERP) {
+ const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
+ opcode_t *const next = cur_opcode + 2;
+ PMC *task = PREG(1);
+ PMC *cur_task;
+ Parrot_Task_attributes *tdata;
+
+ if (!VTABLE_isa(interp, task, Parrot_str_new_constant(interp, "Task")))
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
+ "Argument to wait op must be a Task.\n");
+
+ cur_task = Parrot_cx_stop_task(interp, next);
+ tdata = PARROT_TASK(task);
+ VTABLE_push_pmc(interp, tdata->waiters, cur_task);return (opcode_t *)0;
+
+return (opcode_t *)cur_opcode + 2;}
+
+opcode_t *
+Parrot_wait_pc(opcode_t *cur_opcode, PARROT_INTERP) {
+ const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
+ opcode_t *const next = cur_opcode + 2;
+ PMC *task = CONST(1)->u.key;
+ PMC *cur_task;
+ Parrot_Task_attributes *tdata;
+
+ if (!VTABLE_isa(interp, task, Parrot_str_new_constant(interp, "Task")))
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
+ "Argument to wait op must be a Task.\n");
+
+ cur_task = Parrot_cx_stop_task(interp, next);
+ tdata = PARROT_TASK(task);
+ VTABLE_push_pmc(interp, tdata->waiters, cur_task);return (opcode_t *)0;
+
+return (opcode_t *)cur_opcode + 2;}
+
/*
** op lib descriptor:
@@ -25022,7 +25109,7 @@
2, /* major_version */
5, /* minor_version */
0, /* patch_version */
- 1083, /* op_count */
+ 1086, /* op_count */
core_op_info_table, /* op_info_table */
core_op_func_table, /* op_func_table */
get_op /* op_code() */
Modified: branches/gsoc_threads/src/ops/experimental.ops
==============================================================================
--- branches/gsoc_threads/src/ops/experimental.ops Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/src/ops/experimental.ops Tue Jul 20 01:19:43 2010 (r48117)
@@ -9,6 +9,8 @@
# include <unicode/uchar.h>
#endif
+#include "pmc/pmc_task.h"
+
END_OPS_PREAMBLE
=head1 NAME
@@ -414,6 +416,39 @@
}
}
+=item B<recv>(out PMC)
+
+Recieve a message sent to the current task.
+
+=cut
+
+op recv(out PMC) {
+ opcode_t *const dest = expr NEXT();
+ $1 = PMCNULL;
+}
+
+=item B<wait>(in PMC)
+
+Block and wait for a task to complete.
+
+=cut
+
+op wait(in PMC) {
+ opcode_t *const next = expr NEXT();
+ PMC *task = $1;
+ PMC *cur_task;
+ Parrot_Task_attributes *tdata;
+
+ if (!VTABLE_isa(interp, task, Parrot_str_new_constant(interp, "Task")))
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
+ "Argument to wait op must be a Task.\n");
+
+ cur_task = Parrot_cx_stop_task(interp, next);
+ tdata = PARROT_TASK(task);
+ VTABLE_push_pmc(interp, tdata->waiters, cur_task);
+
+ goto ADDRESS(0);
+}
=back
Modified: branches/gsoc_threads/src/pmc/event.pmc
==============================================================================
--- branches/gsoc_threads/src/pmc/event.pmc Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/src/pmc/event.pmc Tue Jul 20 01:19:43 2010 (r48117)
@@ -64,7 +64,7 @@
core_struct->interp = INTERP;
/* Make sure the flag is cleared by default */
- TASK_terminate_runloop_CLEAR(SELF);
+ /* TASK_terminate_runloop_CLEAR(SELF); */
}
Modified: branches/gsoc_threads/src/pmc/task.pmc
==============================================================================
--- branches/gsoc_threads/src/pmc/task.pmc Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/src/pmc/task.pmc Tue Jul 20 01:19:43 2010 (r48117)
@@ -30,6 +30,8 @@
ATTR PMC *code; /* An (optional) code for the task. */
ATTR PMC *data; /* Additional data for the task. */
ATTR INTVAL killed; /* Dead tasks don't get run. */
+ ATTR PMC *mailbox; /* List of incoming messages. */
+ ATTR PMC *waiters; /* Tasks waiting on this one. */
/*
@@ -53,6 +55,11 @@
core_struct->data = PMCNULL;
core_struct->interp = INTERP;
core_struct->killed = 0;
+ core_struct->mailbox = Parrot_pmc_new(interp, enum_class_PMCList);
+ core_struct->waiters = Parrot_pmc_new(interp, enum_class_ResizablePMCArray);
+
+ /* By default, a task is not being pre-empted */
+ TASK_in_preempt_CLEAR(SELF);
}
/*
@@ -75,10 +82,6 @@
Some data that will be passed to C<code> when invoked.
-=item C<interp>
-
-An interpreter in which to execute this task.
-
=back
=cut
@@ -106,10 +109,6 @@
elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "data"));
if (! PMC_IS_NULL(elem))
core_struct->data = elem;
-
- elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "interp"));
- if (! PMC_IS_NULL(elem))
- core_struct->interp = elem;
}
else {
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
@@ -133,17 +132,27 @@
VTABLE opcode_t *invoke(void *next) {
Parrot_Task_attributes *const task = PARROT_TASK(SELF);
- if (task->killed)
- return (opcode_t*) 0;
+ /* If a task is pre-empted, this will be set again. */
+ TASK_in_preempt_CLEAR(SELF);
- if (PMC_IS_NULL(task->code))
- return (opcode_t*) next;
-
- if (PMC_IS_NULL(task->data)) {
- Parrot_pcc_invoke_sub_from_c_args(interp, task->code, "->");
- }
- else {
- Parrot_pcc_invoke_sub_from_c_args(interp, task->code, "P->", task->data);
+ if (!(task->killed || PMC_IS_NULL(task->code))) {
+ if (PMC_IS_NULL(task->data)) {
+ Parrot_pcc_invoke_sub_from_c_args(interp, task->code, "->");
+ }
+ else {
+ Parrot_pcc_invoke_sub_from_c_args(interp, task->code, "P->", task->data);
+ }
+ }
+
+ if (!TASK_in_preempt_TEST(SELF)) {
+ /* The task is done, schedule any waiters. */
+ int i;
+ int n = VTABLE_get_integer(interp, task->waiters);
+
+ for (i = 0; i < n; ++i) {
+ PMC *wtask = VTABLE_get_pmc_keyed_int(interp, task->waiters, i);
+ Parrot_cx_schedule_task(interp, wtask);
+ }
}
return (opcode_t*) next;
@@ -272,6 +281,8 @@
Parrot_gc_mark_PMC_alive(INTERP, core_struct->code);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->data);
+ Parrot_gc_mark_PMC_alive(INTERP, core_struct->mailbox);
+ Parrot_gc_mark_PMC_alive(INTERP, core_struct->waiters);
}
}
@@ -291,6 +302,8 @@
/* 1) visit code block */
VISIT_PMC_ATTR(INTERP, info, SELF, Task, code);
VISIT_PMC_ATTR(INTERP, info, SELF, Task, data);
+ VISIT_PMC_ATTR(INTERP, info, SELF, Task, mailbox);
+ VISIT_PMC_ATTR(INTERP, info, SELF, Task, waiters);
}
/*
@@ -362,21 +375,8 @@
*/
METHOD send(PMC *message) {
- fprintf(stderr, "Task#send not implemented.\n");
- }
-
-/*
-
-=item METHOD wait()
-
-Block until this task ends.
-
-=cut
-
-*/
-
- METHOD wait() {
- fprintf(stderr, "Task#wait not implemented.\n");
+ Parrot_Task_attributes *tdata = PARROT_TASK(SELF);
+ VTABLE_push_pmc(interp, tdata->mailbox, message);
}
/*
@@ -390,7 +390,8 @@
*/
METHOD kill() {
- fprintf(stderr, "Task#kill not implemented.\n");
+ Parrot_Task_attributes *tdata = PARROT_TASK(SELF);
+ tdata->killed = 1;
}
}
Modified: branches/gsoc_threads/src/scheduler.c
==============================================================================
--- branches/gsoc_threads/src/scheduler.c Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/src/scheduler.c Tue Jul 20 01:19:43 2010 (r48117)
@@ -255,21 +255,18 @@
}
/*
-=item C<opcode_t* Parrot_cx_preempt_task(PARROT_INTERP, PMC *scheduler, opcode_t
-*next)>
+=item C<PMC* Parrot_cx_stop_task(PARROT_INTERP, opcode_t *next)>
-Pre-empt the current task. It goes on the foot of the task queue,
-and then we jump all the way back to the task scheduling loop.
+Stop the current task and pack it up into a PMC what can be used to resume later.
=cut
*/
PARROT_CANNOT_RETURN_NULL
-opcode_t*
-Parrot_cx_preempt_task(PARROT_INTERP, ARGMOD(PMC *scheduler), ARGIN(opcode_t *next))
+PMC*
+Parrot_cx_stop_task(PARROT_INTERP, ARGIN(opcode_t *next))
{
- ASSERT_ARGS(Parrot_cx_preempt_task)
- Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(scheduler);
+ ASSERT_ARGS(Parrot_cx_stop_task)
PMC *task = interp->current_task;
Parrot_Task_attributes *tdata = PARROT_TASK(task);
@@ -279,10 +276,32 @@
if (PMC_IS_NULL(task) || !VTABLE_isa(interp, interp->current_task, CONST_STRING(interp, "Task")))
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
- "Attempt to pre-empt invalid interp->current_task.\n");
+ "Attempt to stop invalid interp->current_task.\n");
tdata->code = cont;
+ TASK_in_preempt_SET(task);
+
+ return task;
+}
+
+/*
+=item C<opcode_t* Parrot_cx_preempt_task(PARROT_INTERP, PMC *scheduler, opcode_t
+*next)>
+
+Pre-empt the current task. It goes on the foot of the task queue,
+and then we jump all the way back to the task scheduling loop.
+
+=cut
+*/
+
+PARROT_CANNOT_RETURN_NULL
+opcode_t*
+Parrot_cx_preempt_task(PARROT_INTERP, ARGMOD(PMC *scheduler), ARGIN(opcode_t *next))
+{
+ ASSERT_ARGS(Parrot_cx_preempt_task)
+ Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(scheduler);
+ PMC* task = Parrot_cx_stop_task(interp, next);
VTABLE_push_pmc(interp, sched->task_queue, task);
interp->current_task = PMCNULL;
Modified: branches/gsoc_threads/t/pmc/task.t
==============================================================================
--- branches/gsoc_threads/t/pmc/task.t Mon Jul 19 21:54:44 2010 (r48116)
+++ branches/gsoc_threads/t/pmc/task.t Tue Jul 20 01:19:43 2010 (r48117)
@@ -1,19 +1,116 @@
-#! parrot
+#!./parrot
# Copyright (C) 2010, Parrot Foundation.
# $Id$
.sub main
.include 'test_more.pir'
- plan(1)
+ plan(9)
- ok1()
+ tasks_run_in_order()
+ task_send_recv()
+ task_kill()
+ task_wait()
+
+ $P0 = get_global 'exit0'
+ $P1 = new 'Task', $P0
+ schedule $P1
- $P0 = new 'Task'
+again:
+ goto again
.end
-.sub ok1
- say "ok 1"
+.sub tasks_run_in_order
+ $P0 = new 'Integer', 0
+ set_global 'N', $P0
+
+ $P0 = get_global 'task1'
+ $P1 = new 'Task', $P0
+ schedule $P1
+
+ $P0 = get_global 'sub1'
+ schedule $P0
+
+ $P0 = get_global 'task2'
+ $P1 = new 'Task', $P0
+ schedule $P1
+
+ sleep 0.01
+.end
+
+.sub task1
+ $P0 = get_global 'N'
+ is($P0, 0, "Task ran in order (0)")
+
+ $P0 = 1
+ set_global 'N', $P0
+.end
+
+.sub sub1
+ $P0 = get_global 'N'
+ is($P0, 1, "Implicit task ran in order (2)")
+
+ $P0 = 2
+ set_global 'N', $P0
+.end
+
+.sub task2
+ $P0 = get_global 'N'
+ is($P0, 2, "Task ran in order (3)")
+
+ $P0 = 3
+ set_global 'N', $P0
+.end
+
+.sub task_send_recv
+ $P0 = get_global 'recv_msg'
+ $P1 = new 'Task', $P0
+ $P2 = new 'String'
+ $P2 = "Hai"
+ $P1.'send'($P2)
+ schedule $P1
+.end
+
+.sub task_kill
+ $P0 = get_global 'task_to_kill'
+ $P1 = new 'Task', $P0
+ schedule $P1
+ sleep 0.001
+ $P1.'kill'()
+ sleep 0.1
+ ok(1, "task_to_kill killed")
+.end
+
+.sub task_to_kill
+ ok(1, "task_to_kill running")
+ sleep 0.05
+ ok(0, "task_to_kill wasn't killed")
+.end
+
+.sub recv_msg
+ $P0 = recv
+ $P1 = new 'String'
+ $P1 = "Hai"
+#is($P0, $P1, "Got message")
+ skip("Chandon TODO: Message Passing")
+.end
+
+.sub task_wait
+ $P0 = get_global 'wait_sub1'
+ $P1 = new 'Task', $P0
+ schedule $P1
+
+ wait $P1
+ ok(1, "After wait")
+.end
+
+.sub wait_sub1
+ ok(1, "in wait_sub1")
+.end
+
+.sub exit0
+ ok(1, "Pre-empt and exit")
+ exit 0
.end
# Local Variables:
More information about the parrot-commits
mailing list