From 5464a7a3793fe52d8ecd42b7205e00bcf3c9f634 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Mon, 30 Aug 2021 22:22:22 -0500 Subject: [PATCH] Allow passing a function to directly to ev/go. Makes ev/call less useful but ev/go more useful. No need to construct as many identical intermediate fibers. --- examples/evsleep.janet | 10 ++++++++++ src/boot/boot.janet | 10 +++++----- src/core/ev.c | 26 ++++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/examples/evsleep.janet b/examples/evsleep.janet index 9ceeef0c..b2b0ea89 100644 --- a/examples/evsleep.janet +++ b/examples/evsleep.janet @@ -10,3 +10,13 @@ (ev/call worker :b 5) (ev/sleep 0.3) (ev/call worker :c 12) + +(defn worker2 + [name] + (repeat 10 + (ev/sleep 0.2) + (print name " working"))) + +(ev/go worker2 :bob) +(ev/go worker2 :joe) +(ev/go worker2 :sally) diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 170a8a50..b6029391 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -3360,23 +3360,23 @@ Returns a fiber that is scheduled to run the function. ``` [f & args] - (ev/go (fiber/new (fn [&] (f ;args)) :tp))) + (ev/go (fn _call [&] (f ;args)))) (defmacro ev/spawn "Run some code in a new fiber. This is shorthand for (ev/call (fn [] ;body))." [& body] - ~(,ev/go (fiber/new (fn _spawn [&] ,;body) :tp))) + ~(,ev/go (fn _spawn [&] ,;body))) (defmacro ev/do-thread ``Run some code in a new thread. Suspends the current fiber until the thread is complete, and evaluates to nil.`` [& body] - ~(,ev/thread (fiber/new (fn _thread [&] ,;body) :t))) + ~(,ev/thread (fn _do-thread [&] ,;body))) (defmacro ev/spawn-thread ``Run some code in a new thread. Like `ev/do-thread`, but returns nil immediately.`` [& body] - ~(,ev/thread (fiber/new (fn _thread [&] ,;body) :t) nil :n)) + ~(,ev/thread (fn _spawn-thread [&] ,;body) nil :n)) (defmacro ev/with-deadline `Run a body of code with a deadline, such that if the code does not complete before @@ -3407,7 +3407,7 @@ (def ,res @[]) (,wait-for-fibers ,chan ,(seq [[i body] :pairs bodies] - ~(,ev/go (,fiber/new (fn [] (put ,res ,i ,body)) :tp) nil ,chan))) + ~(,ev/go (fn [] (put ,res ,i ,body)) nil ,chan))) ,res)))) (compwhen (dyn 'net/listen) diff --git a/src/core/ev.c b/src/core/ev.c index ab981fd3..65887441 100644 --- a/src/core/ev.c +++ b/src/core/ev.c @@ -2443,12 +2443,34 @@ JANET_CORE_FN(cfun_ev_go, "events occur in the newly scheduled fiber, an event will be pushed to the supervisor. " "If not provided, the new fiber will inherit the current supervisor.") { janet_arity(argc, 1, 3); - JanetFiber *fiber = janet_getfiber(argv, 0); Janet value = argc >= 2 ? argv[1] : janet_wrap_nil(); void *supervisor = janet_optabstract(argv, argc, 2, &janet_channel_type, janet_vm.root_fiber->supervisor_channel); + JanetFiber *fiber; + if (janet_checktype(argv[0], JANET_FUNCTION)) { + /* Create a fiber for the user */ + JanetFunction *func = janet_unwrap_function(argv[0]); + if (func->def->min_arity > 1) { + janet_panicf("task function must accept 0 or 1 arguments"); + } + fiber = janet_fiber(func, 64, func->def->min_arity, &value); + fiber->flags |= + JANET_FIBER_MASK_ERROR | + JANET_FIBER_MASK_USER0 | + JANET_FIBER_MASK_USER1 | + JANET_FIBER_MASK_USER2 | + JANET_FIBER_MASK_USER3 | + JANET_FIBER_MASK_USER4; + if (!janet_vm.fiber->env) { + janet_vm.fiber->env = janet_table(0); + } + fiber->env = janet_table(0); + fiber->env->proto = janet_vm.fiber->env; + } else { + fiber = janet_getfiber(argv, 0); + } fiber->supervisor_channel = supervisor; janet_schedule(fiber, value); - return argv[0]; + return janet_wrap_fiber(fiber); } /* For ev/thread - Run an interpreter in the new thread. */