mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
Add lock_update function for safer multithreading
&v = (v, 1).sum might fail if two threads do it at the same time or something, so you can now lock the reference to ensure no other thread messes with your data while you update its value
This commit is contained in:
parent
68d5b55c6f
commit
8bdd6e00e8
@ -92,8 +92,6 @@ fn main() {
|
||||
std::process::exit(36);
|
||||
}
|
||||
};
|
||||
#[cfg(debug_assertions)]
|
||||
dbg!(&return_type);
|
||||
if args.check == Check::Yes {
|
||||
run.run(&mut info_run);
|
||||
} else {
|
||||
|
@ -6,7 +6,7 @@ pub fn assign(from: &Data, target: &Data) {
|
||||
.as_any()
|
||||
.downcast_ref::<crate::data::reference::Reference>()
|
||||
{
|
||||
*r.0.lock().unwrap() = from.clone();
|
||||
*r.0.write().unwrap() = from.clone();
|
||||
} else if let (Some(from), Some(target)) = (
|
||||
from.get()
|
||||
.as_any()
|
||||
|
@ -1,18 +1,18 @@
|
||||
use std::{
|
||||
any::Any,
|
||||
fmt::Display,
|
||||
sync::{Arc, Mutex},
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
use super::{Data, MersData, MersType, Type};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Reference(pub Arc<Mutex<Data>>);
|
||||
pub struct Reference(pub Arc<RwLock<Data>>);
|
||||
|
||||
impl MersData for Reference {
|
||||
fn is_eq(&self, other: &dyn MersData) -> bool {
|
||||
if let Some(other) = other.as_any().downcast_ref::<Self>() {
|
||||
*other.0.lock().unwrap() == *self.0.lock().unwrap()
|
||||
*other.0.write().unwrap() == *self.0.write().unwrap()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -21,7 +21,7 @@ impl MersData for Reference {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_type(&self) -> Type {
|
||||
Type::new(ReferenceT(self.0.lock().unwrap().get().as_type()))
|
||||
Type::new(ReferenceT(self.0.write().unwrap().get().as_type()))
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
@ -69,7 +69,7 @@ impl MersType for ReferenceT {
|
||||
|
||||
impl Display for Reference {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "&{}", self.0.lock().unwrap().get())
|
||||
write!(f, "&{}", self.0.write().unwrap().get())
|
||||
}
|
||||
}
|
||||
impl Display for ReferenceT {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use crate::{
|
||||
data::{Data, Type},
|
||||
@ -69,7 +69,7 @@ impl Config {
|
||||
pub fn add_var(mut self, name: String, val: Data) -> Self {
|
||||
let t = val.get().as_type();
|
||||
self.info_parsed.scopes[0].init_var(name, (0, self.globals));
|
||||
self.info_run.scopes[0].init_var(self.globals, Arc::new(Mutex::new(val)));
|
||||
self.info_run.scopes[0].init_var(self.globals, Arc::new(RwLock::new(val)));
|
||||
self.info_check.scopes[0].init_var(self.globals, t);
|
||||
self.globals += 1;
|
||||
self
|
||||
|
@ -19,6 +19,7 @@ impl Config {
|
||||
/// `len: fn` gets the length of strings or tuples
|
||||
/// `sleep: fn` sleeps for n seconds (pauses the current thread)
|
||||
/// `panic: fn` exits the program with the given exit code
|
||||
/// `lock_update: fn` locks the value of a reference so you can exclusively modify it: &var.lock_update(v -> (v, 1).sum)
|
||||
pub fn with_base(self) -> Self {
|
||||
self.add_var("try".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
@ -112,6 +113,54 @@ impl Config {
|
||||
unreachable!("try: no function found")
|
||||
})
|
||||
}))
|
||||
.add_var("lock_update".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Arc::new(|a, _i| {
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
if t.0.len() == 2 {
|
||||
let arg_ref = &t.0[0];
|
||||
if let Some(arg) = arg_ref.dereference() {
|
||||
let func = &t.0[1];
|
||||
for func_t in func.types.iter() {
|
||||
if let Some(f) = func_t.as_any().downcast_ref::<data::function::FunctionT>() {
|
||||
match (f.0)(&arg) {
|
||||
Ok(out) => {
|
||||
if !out.is_included_in(&arg) {
|
||||
return Err(format!("Function returns a value of type {out}, which isn't included in the type of the reference, {arg}.").into());
|
||||
}
|
||||
},
|
||||
Err(e) => return Err(CheckError::new().msg(format!("Invalid argument type {arg} for function")).err(e)),
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Arguments must be (reference, function)").into());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Arguments must be (reference, function), but {arg_ref} isn't a reference").into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Can't call lock_update on tuple type {t} with length != 2, which is part of the argument type {a}.").into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Can't call lock_update on non-tuple type {t}, which is part of the argument type {a}.").into());
|
||||
}
|
||||
}
|
||||
Ok(Type::empty_tuple())
|
||||
}),
|
||||
run: Arc::new(|a, _i| {
|
||||
let a = a.get();
|
||||
let a = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
|
||||
let arg_ref = a.0[0].get();
|
||||
let arg_ref = arg_ref.as_any().downcast_ref::<data::reference::Reference>().unwrap();
|
||||
let mut arg = arg_ref.0.write().unwrap();
|
||||
let func = a.0[1].get();
|
||||
let func = func.as_any().downcast_ref::<data::function::Function>().unwrap();
|
||||
*arg = func.run(arg.clone());
|
||||
Data::empty_tuple()
|
||||
})
|
||||
}))
|
||||
.add_var("sleep".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
@ -268,7 +317,7 @@ impl Config {
|
||||
.as_any()
|
||||
.downcast_ref::<data::reference::Reference>()
|
||||
{
|
||||
r.0.lock().unwrap().clone()
|
||||
r.0.write().unwrap().clone()
|
||||
} else {
|
||||
unreachable!("called deref on non-reference")
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ impl Config {
|
||||
.downcast_ref::<data::reference::Reference>()
|
||||
.unwrap()
|
||||
.0
|
||||
.lock()
|
||||
.write()
|
||||
.unwrap()
|
||||
.get_mut()
|
||||
.mut_any()
|
||||
@ -118,7 +118,7 @@ impl Config {
|
||||
.downcast_ref::<data::reference::Reference>()
|
||||
.unwrap()
|
||||
.0
|
||||
.lock()
|
||||
.write()
|
||||
.unwrap()
|
||||
.get_mut()
|
||||
.mut_any()
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
fmt::{Debug, Display},
|
||||
sync::{Arc, Mutex},
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
use colored::Colorize;
|
||||
@ -240,7 +240,7 @@ pub type CheckInfo = info::Info<CheckLocal>;
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct Local {
|
||||
vars: Vec<Arc<Mutex<Data>>>,
|
||||
vars: Vec<Arc<RwLock<Data>>>,
|
||||
}
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct CheckLocal {
|
||||
@ -248,9 +248,9 @@ pub struct CheckLocal {
|
||||
}
|
||||
impl info::Local for Local {
|
||||
type VariableIdentifier = usize;
|
||||
type VariableData = Arc<Mutex<Data>>;
|
||||
type VariableData = Arc<RwLock<Data>>;
|
||||
fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) {
|
||||
let nothing = Arc::new(Mutex::new(Data::new(data::bool::Bool(false))));
|
||||
let nothing = Arc::new(RwLock::new(Data::new(data::bool::Bool(false))));
|
||||
while self.vars.len() <= id {
|
||||
self.vars.push(Arc::clone(¬hing));
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use crate::data::{self, Data, Type};
|
||||
|
||||
@ -40,7 +40,7 @@ impl MersStatement for Variable {
|
||||
}
|
||||
fn run_custom(&self, info: &mut super::Info) -> Data {
|
||||
if self.is_init {
|
||||
let nothing = Arc::new(Mutex::new(Data::new(data::bool::Bool(false))));
|
||||
let nothing = Arc::new(RwLock::new(Data::new(data::bool::Bool(false))));
|
||||
while info.scopes[self.var.0].vars.len() <= self.var.1 {
|
||||
info.scopes[self.var.0].vars.push(Arc::clone(¬hing));
|
||||
}
|
||||
@ -52,7 +52,7 @@ impl MersStatement for Variable {
|
||||
)))
|
||||
} else {
|
||||
info.scopes[self.var.0].vars[self.var.1]
|
||||
.lock()
|
||||
.write()
|
||||
.unwrap()
|
||||
.clone()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user