From 5b501c7a8c68847887b0798092d3cd541f6341ec Mon Sep 17 00:00:00 2001 From: TudbuT Date: Thu, 30 Jan 2025 07:19:36 +0100 Subject: [PATCH] synchronization --- spl/std.spl | 17 +++++++++++++++++ src/std_fns.rs | 22 +++++++++++++++++++++- test.spl | 28 ++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/spl/std.spl b/spl/std.spl index 2a403bf..22e5bf0 100644 --- a/spl/std.spl +++ b/spl/std.spl @@ -905,3 +905,20 @@ func register-field { | with field-name namespace-name ; iter:next dyn-call iter:foreach<&dyn-objcall> } + + +construct Synchronizer { + sync + ; + construct { this | with this ; + 0 this:=sync + this + } + do { | with callable this ; + "will increment the sync field if and only if it is zero. when it was incremented (returned zero), the loop will exit"; + while { this "sync" atomic-get-inc-if-zero } { yield } + callable:call + 0 this:=sync + } +} + diff --git a/src/std_fns.rs b/src/std_fns.rs index 57e1593..2c5909b 100644 --- a/src/std_fns.rs +++ b/src/std_fns.rs @@ -1014,6 +1014,11 @@ pub fn time(stack: &mut Stack) -> OError { Ok(()) } +pub fn thread_yield(stack: &mut Stack) -> OError { + thread::yield_now(); + Ok(()) +} + pub fn str_readf(stack: &mut Stack) -> OError { require_on_stack!(string, Str, stack, "str-readf"); require_on_stack!(pat, Str, stack, "str-readf"); @@ -1275,9 +1280,22 @@ pub fn json_parse(stack: &mut Stack) -> OError { Ok(()) } +pub fn atomic_get_inc_if_zero(stack: &mut Stack) -> OError { + require_on_stack!(field, Str, stack, "atomic-get-inc-if-zero"); + let o = stack.pop(); + let o = o.lock_ro(); + let f = o.field(&field, stack)?; + let mut f = f.lock(); + stack.push(f.clone().spl()); + if f.native == Value::Mega(0) { + f.native = Value::Mega(1); + } + Ok(()) +} + pub fn register(r: &mut Stack, o: Arc) { type Fn = fn(&mut Stack) -> OError; - let fns: [(&str, Fn, u32); 71] = [ + let fns: [(&str, Fn, u32); 73] = [ ("pop", pop, 0), ("dup", dup, 2), ("dup2", dup2, 3), @@ -1340,6 +1358,7 @@ pub fn register(r: &mut Stack, o: Arc) { ("write-file-sasm", write_file_sasm, 1), ("fork", fork, 0), ("sleeptime", time, 0), + ("yield", thread_yield, 0), ("str-readf", str_readf, 1), ("str-to-mega-radix", str_to_mega_radix, 1), ("mega-to-str-radix", mega_to_str_radix, 1), @@ -1349,6 +1368,7 @@ pub fn register(r: &mut Stack, o: Arc) { ("delete-file", delete_file, 1), ("delete-dir", delete_dir, 1), ("chdir", chdir, 0), + ("atomic-get-inc-if-zero", atomic_get_inc_if_zero, 1), // ("json-parse", json_parse, 1), ]; for f in fns { diff --git a/test.spl b/test.spl index 1290f8e..ba833ba 100644 --- a/test.spl +++ b/test.spl @@ -464,6 +464,34 @@ func main { int | with args ; println } + + "" println; + "testing sync (should be 5)" println; + + def x 5 =x + def sync Synchronizer:new =sync + + 10 :foreach<| + fork<| 10 :foreach<| sync:do<| x ++ =x > > > + fork<| 10 :foreach<| sync:do<| x -- =x > > > + > + + 1000 time:sleep; + + x println + + "nonsynced for comparison:" println + + def x 5 =x + + 10 :foreach<| + fork<| 10 :foreach<| x ++ =x > > + fork<| 10 :foreach<| x -- =x > > + > + + 1000 time:sleep; + + x println