From 957a513fd64f4ca5daa6e6bf08df65e6c469e08a Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 1 Jul 2017 11:17:29 -0400 Subject: [PATCH] More changes to threading model. --- core/vm.c | 42 +++++++++++++++++++++++++++++++----------- gsttests/basic.gst | 17 ++++++++++------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/core/vm.c b/core/vm.c index a434a938..ce806bf4 100644 --- a/core/vm.c +++ b/core/vm.c @@ -40,6 +40,7 @@ int gst_continue(Gst *vm) { #define gst_assert(vm, cond, e) do {if (!(cond)){gst_error((vm), (e));}} while (0) /* Intialize local state */ + vm->thread->status = GST_THREAD_ALIVE; stack = gst_thread_stack(vm->thread); pc = gst_frame_pc(stack); @@ -356,14 +357,20 @@ int gst_continue(Gst *vm) { case GST_OP_TRN: /* Transfer */ temp = stack[pc[2]]; /* The thread */ v1 = stack[pc[3]]; /* The value to pass in */ - if (temp.type != GST_THREAD) + if (temp.type != GST_THREAD && temp.type != GST_NIL) gst_error(vm, "expected thread"); - if (temp.data.thread->status == GST_THREAD_DEAD || - temp.data.thread->status == GST_THREAD_ERROR) - gst_error(vm, "cannot enter dead thread"); + if (temp.type == GST_THREAD) { + if (temp.data.thread->status == GST_THREAD_DEAD || + temp.data.thread->status == GST_THREAD_ERROR) + gst_error(vm, "cannot enter dead thread"); + } gst_frame_ret(stack) = pc[1]; vm->thread->status = GST_THREAD_PENDING; gst_frame_pc(stack) = pc + 4; + if (temp.type == GST_NIL) { + vm->ret = v1; + return GST_RETURN_OK; + } temp.data.thread->status = GST_THREAD_ALIVE; vm->thread = temp.data.thread; stack = gst_thread_stack(temp.data.thread); @@ -423,22 +430,35 @@ int gst_continue(Gst *vm) { /* Run the vm with a given function. This function is * called to start the vm. */ int gst_run(Gst *vm, GstValue callee) { - if (vm->thread == NULL) { - vm->thread = gst_thread(vm, callee, 64); - } else { + int result; + if (vm->thread && + (vm->thread->status == GST_THREAD_DEAD || + vm->thread->status == GST_THREAD_ALIVE)) { /* Reuse old thread */ gst_thread_reset(vm, vm->thread, callee); + } else { + /* Create new thread */ + vm->thread = gst_thread(vm, callee, 64); + if (vm->thread == NULL) + return GST_RETURN_CRASH; } - if (vm->thread == NULL) - return GST_RETURN_CRASH; if (callee.type == GST_CFUNCTION) { vm->ret.type = GST_NIL; - return callee.data.cfunction(vm); + result = callee.data.cfunction(vm); } else if (callee.type == GST_FUNCTION) { - return gst_continue(vm); + result = gst_continue(vm); } else { return GST_RETURN_CRASH; } + /* Handle yields */ + while (result == GST_RETURN_OK && vm->thread->status == GST_THREAD_PENDING) { + /* Send back in the value yielded - TODO - do something useful with this */ + GstValue *stack = gst_thread_stack(vm->thread); + stack[gst_frame_ret(stack)] = vm->ret; + /* Resume */ + result = gst_continue(vm); + } + return result; } /* Get an argument from the stack */ diff --git a/gsttests/basic.gst b/gsttests/basic.gst index fdce7ab0..5a067765 100644 --- a/gsttests/basic.gst +++ b/gsttests/basic.gst @@ -1,14 +1,17 @@ (print "Running basic tests...") -(var numTestsPassed 0) -(def assert (fn [x e] +(var num-tests-passed 0) +(var num-tests-run 0) +(def assert (fn [x e] + (varset! num-tests-run (+ 1 num-tests-run)) (if x (do (print " \e[32m✔\e[0m" e) - (varset! numTestsPassed (+ 1 numTestsPassed)) x) + (varset! num-tests-passed (+ 1 num-tests-passed)) + x) (do - (print e) - (exit! (+ numTestsPassed 1)))))) + (print " \e[31m✘\e[0m" e) + x)))) (assert (= 10 (+ 1 2 3 4)) "addition") (assert (= -8 (- 1 2 3 4)) "subtraction") @@ -77,7 +80,7 @@ (assert (= athread-result "hello, world!") "thread error result") (assert (= (status athread) "error") "thread error status") -"All tests passed" +"report" -(print "All" numTestsPassed "tests passed") +(print num-tests-passed "of" num-tests-run "tests passed") (exit! 0) \ No newline at end of file