Add some more fiber functions.

Add fiber.current and fiber.lineage
This commit is contained in:
Calvin Rose 2018-05-10 20:25:49 -04:00
parent 584c75b3f6
commit ee01547b3a
5 changed files with 47 additions and 6 deletions

View File

@ -904,7 +904,7 @@ onvalue."
(res)
(do
(:= good false)
(onerr "compile" (get res :error))))) :de))
(onerr "compile" (get res :error))))) :dey))
(def res (fiber.resume f))
(if good
(cond

View File

@ -268,11 +268,11 @@ static int cfun_new(DstArgs args) {
const uint8_t *flags;
int32_t len, i;
dst_arg_bytes(flags, len, args, 1);
fiber->flags |= DST_FIBER_MASK_ERROR;
fiber->flags |= DST_FIBER_MASK_ERROR | DST_FIBER_MASK_YIELD;
for (i = 0; i < len; i++) {
switch (flags[i]) {
default:
return dst_throw(args, "invalid flag, expected d or e");
return dst_throw(args, "invalid flag, expected d, e, or y");
case ':':
break;
case 'd':
@ -281,6 +281,9 @@ static int cfun_new(DstArgs args) {
case 'e':
fiber->flags &= ~DST_FIBER_MASK_ERROR;
break;
case 'y':
fiber->flags &= ~DST_FIBER_MASK_YIELD;
break;
}
}
}
@ -367,10 +370,31 @@ static int cfun_stack(DstArgs args) {
return dst_return(args, dst_wrap_array(array));
}
static int cfun_current(DstArgs args) {
dst_fixarity(args, 0);
return dst_return(args, dst_wrap_fiber(dst_vm_fiber));
}
static int cfun_lineage(DstArgs args) {
DstFiber *fiber;
DstArray *array;
dst_fixarity(args, 1);
dst_check(args, 0, DST_FIBER);
fiber = dst_unwrap_fiber(args.v[0]);
array = dst_array(0);
while (fiber) {
dst_array_push(array, dst_wrap_fiber(fiber));
fiber = fiber->child;
}
return dst_return(args, dst_wrap_array(array));
}
static const DstReg cfuns[] = {
{"fiber.new", cfun_new},
{"fiber.status", cfun_status},
{"fiber.stack", cfun_stack},
{"fiber.current", cfun_current},
{"fiber.lineage", cfun_lineage},
{NULL, NULL}
};

View File

@ -25,6 +25,8 @@
#include <dst/dst.h>
extern DST_THREAD_LOCAL DstFiber *dst_vm_fiber;
#define dst_stack_frame(s) ((DstStackFrame *)((s) - DST_FRAME_SIZE))
#define dst_fiber_frame(f) dst_stack_frame((f)->data + (f)->frame)
DstFiber *dst_fiber_reset(DstFiber *fiber, DstFunction *callee);

View File

@ -29,6 +29,7 @@
/* VM state */
DST_THREAD_LOCAL int dst_vm_stackn = 0;
DST_THREAD_LOCAL DstFiber *dst_vm_fiber = NULL;
/* Maybe collect garbage */
#define dst_maybe_collect() do {\
@ -37,6 +38,9 @@ DST_THREAD_LOCAL int dst_vm_stackn = 0;
/* Start running the VM from where it left off. */
Dst dst_run(DstFiber *fiber) {
/* Save old fiber to reset */
DstFiber *old_vm_fiber = dst_vm_fiber;
/* VM state */
register Dst *stack;
register uint32_t *pc;
@ -53,13 +57,14 @@ Dst dst_run(DstFiber *fiber) {
}
dst_vm_stackn++;
/* Reset fiber state */
/* Setup fiber state */
dst_vm_fiber = fiber;
dst_gcroot(dst_wrap_fiber(fiber));
if (fiber->flags & DST_FIBER_FLAG_NEW) {
dst_fiber_funcframe(fiber, fiber->root);
fiber->flags &= ~DST_FIBER_FLAG_NEW;
}
fiber->status = DST_FIBER_ALIVE;
dst_gcroot(dst_wrap_fiber(fiber));
stack = fiber->data + fiber->frame;
pc = dst_stack_frame(stack)->pc;
func = dst_stack_frame(stack)->func;
@ -202,7 +207,7 @@ static void *op_lookup[255] = {
vm_next();\
}
/* Main interpreter loop. Sematically is a switch on
/* Main interpreter loop. Semantically is a switch on
* (*pc & 0xFF) inside of an infinte loop. */
VM_START();
@ -739,6 +744,7 @@ static void *op_lookup[255] = {
}
fiber->child = nextfiber;
retreg = dst_run(nextfiber);
dst_vm_fiber = fiber;
switch (nextfiber->status) {
case DST_FIBER_DEBUG:
if (nextfiber->flags & DST_FIBER_MASK_DEBUG) goto vm_debug;
@ -748,6 +754,13 @@ static void *op_lookup[255] = {
if (nextfiber->flags & DST_FIBER_MASK_ERROR) goto vm_error;
fiber->child = NULL;
break;
case DST_FIBER_PENDING:
if (nextfiber->flags & DST_FIBER_MASK_YIELD) {
fiber->status = DST_FIBER_PENDING;
goto vm_exit;
}
fiber->child = NULL;
break;
default:
fiber->child = NULL;
break;
@ -853,6 +866,7 @@ static void *op_lookup[255] = {
dst_stack_frame(stack)->pc = pc;
dst_vm_stackn--;
dst_gcunroot(dst_wrap_fiber(fiber));
dst_vm_fiber = old_vm_fiber;
return retreg;
}

View File

@ -344,6 +344,7 @@ struct DstArgs {
/* Fiber signal masks. Should not overlap any fiber flags. */
#define DST_FIBER_MASK_ERROR 1
#define DST_FIBER_MASK_DEBUG 2
#define DST_FIBER_MASK_YIELD 4
/* A lightweight green thread in dst. Does not correspond to
* operating system threads. */