Permalink
Browse files

Make embed API invoke work with green threads

Task now have an optional signature data attribute which can be passed to
to Parrot_pcc_invoke_from_sig_object directly instead of creating a
signature using Parrot_ext_call.

This is used to have Parrot_api_pmc_invoke create a task and invoke the
scheduler's outer runloop instead of invoking the given sub directly.
This way the green threads infratructure is used correctly and ops like
sleep should work.
  • Loading branch information...
1 parent 03e14e3 commit 5ee91fa6268ffab98a51fe7ad9a15a704d6acb3c @niner niner committed Jul 14, 2012
Showing with 26 additions and 3 deletions.
  1. +2 −1 config/gen/makefiles/root.in
  2. +12 −1 src/embed/pmc.c
  3. +12 −1 src/pmc/task.pmc
@@ -1869,7 +1869,8 @@ src/embed/pmc$(O) : \
$(INC_DIR)/api.h \
src/embed/pmc.c \
src/embed/embed_private.h \
- $(INC_PMC_DIR)/pmc_parrotinterpreter.h
+ $(INC_PMC_DIR)/pmc_parrotinterpreter.h \
+ $(INC_PMC_DIR)/pmc_task.h
src/dataypes$(O) : $(GEN_HEADERS) src/dataypes.c
View
@@ -20,6 +20,7 @@ This file implements PMC functions of the Parrot embedding interface.
#include "parrot/parrot.h"
#include "parrot/api.h"
#include "embed_private.h"
+#include "pmc/pmc_task.h"
/* HEADERIZER HFILE: include/parrot/api.h */
@@ -541,7 +542,17 @@ Parrot_api_pmc_invoke(ARGIN(Parrot_PMC interp_pmc), ARGIN(Parrot_PMC sub),
EMBED_API_CALLIN(interp_pmc, interp)
PMC * const old_call_obj = Parrot_pcc_get_signature(interp,
CURRENT_CONTEXT(interp));
- Parrot_pcc_invoke_from_sig_object(interp, sub, signature);
+
+ PMC * const task = Parrot_pmc_new(interp, enum_class_Task);
+ Parrot_Task_attributes * const tdata = PARROT_TASK(task);
+
+ tdata->code = sub;
+ tdata->signature = signature;
+ PARROT_GC_WRITE_BARRIER(interp, task);
+
+ Parrot_cx_schedule_immediate(interp, task);
+ Parrot_cx_outer_runloop(interp);
+
Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_call_obj);
EMBED_API_CALLOUT(interp_pmc, interp)
}
View
@@ -32,6 +32,7 @@ pmclass Task provides invokable auto_attrs {
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 INTVAL signature; /* data is a call signature */
ATTR PMC *mailbox; /* List of incoming messages */
ATTR Parrot_mutex mailbox_lock;
ATTR PMC *waiters; /* Tasks waiting on this one */
@@ -62,6 +63,7 @@ Initialize a concurrency task object.
core_struct->birthtime = Parrot_floatval_time();
core_struct->code = PMCNULL;
core_struct->data = PMCNULL;
+ core_struct->signature = PMCNULL;
core_struct->interp = INTERP;
core_struct->killed = 0;
core_struct->mailbox = PMCNULL; /* Created lazily on demand */
@@ -129,6 +131,10 @@ Some data that will be passed to C<code> when invoked.
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, "signature"));
+ if (! PMC_IS_NULL(elem))
+ core_struct->signature = elem;
}
else {
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
@@ -170,7 +176,12 @@ code as the first argument.
TASK_active_SET(SELF);
/* Actually run the task */
- Parrot_ext_call(interp, task->code, "P->", task->data);
+ if (task->signature != PMCNULL) {
+ Parrot_pcc_invoke_from_sig_object(interp, task->code, task->signature);
+ }
+ else {
+ Parrot_ext_call(interp, task->code, "P->", task->data);
+ }
/* Restore recursion_depth since Parrot_Sub_invoke increments recursion_depth
which would not be decremented anymore if the sub is preempted */
Parrot_pcc_set_recursion_depth(interp, CURRENT_CONTEXT(interp), current_depth);

0 comments on commit 5ee91fa

Please sign in to comment.