diff --git a/docs/scarpet/language/SystemFunctions.md b/docs/scarpet/language/SystemFunctions.md index 9a23faa3..e9e2b8df 100644 --- a/docs/scarpet/language/SystemFunctions.md +++ b/docs/scarpet/language/SystemFunctions.md @@ -100,22 +100,21 @@ from other threads, just because the only possibility of a deadlock in this case bad code, not the internal world access behaviour. Some things tough like player or entity manipulation, can be effectively parallelized. -### `task(function, ?args...., ?executor)` +### `task(function, ... args)`, `task_thread(executor, function, ... args)` Creates and runs a parallel task, returning the handle to the task object. Task will return the return value of the function when its completed, or will return `null` immediately if task is still in progress, so grabbing a value of a task object is non-blocking. Function can be either function value, or function lambda, or a name of an existing defined function. In case function needs arguments to be called with, they should be supplied after the function -name, or value. Optional `executor` identifier is to place the task in a specific queue identified by this value. -The default thread value is the `null` thread. There is no limits on number of parallel tasks for any executor, -so using different queues is solely for synchronization purposes. Also, since `task` function knows how many extra -arguments it requires, the use of tailing optional parameter for the custom executor thread pool is not ambiguous. +name, or value. `executor` identifier in `task_thread`, places the task in a specific queue identified by this value. +The default thread value is the `null` thread. There are no limits on number of parallel tasks for any executor, +so using different queues is solely for synchronization purposes.
 task( _() -> print('Hello Other World') )  => Runs print command on a separate thread
 foo(a, b) -> print(a+b); task('foo',2,2)  => Uses existing function definition to start a task
-task('foo',3,5,'temp');  => runs function foo with a different thread executor, identified as 'temp'
-a = 3; task( _(outer(a), b) -> foo(a,b), 5, 'temp')  
+task_thread('temp', 'foo',3,5);  => runs function foo with a different thread executor, identified as 'temp'
+a = 3; task_thread('temp', _(outer(a), b) -> foo(a,b), 5)  
     => Another example of running the same thing passing arguments using closure over anonymous function as well as passing a parameter.
 
diff --git a/src/main/java/carpet/script/language/Threading.java b/src/main/java/carpet/script/language/Threading.java index 40e4f23b..781d093e 100644 --- a/src/main/java/carpet/script/language/Threading.java +++ b/src/main/java/carpet/script/language/Threading.java @@ -15,14 +15,24 @@ public class Threading { if (lv.size() == 0) throw new InternalExpressionException("'task' requires at least function to call as a parameter"); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, true, false); - Value queue = Value.NULL; - if (lv.size() > functionArgument.offset) queue = lv.get(functionArgument.offset).evalValue(c); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, true, true); + ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.args); + Thread.yield(); + return (cc, tt) -> thread; + }); + + expression.addLazyFunctionWithDelegation("task_thread", -1, (c, t, expr, tok, lv) -> + { + if (lv.size() < 2) + throw new InternalExpressionException("'task' requires at least function to call as a parameter"); + Value queue = lv.get(0).evalValue(c); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, true, true); ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.args); Thread.yield(); return (cc, tt) -> thread; }); + expression.addFunction("task_count", (lv) -> { if (lv.size() > 0)