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);
|
std::process::exit(36);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
dbg!(&return_type);
|
|
||||||
if args.check == Check::Yes {
|
if args.check == Check::Yes {
|
||||||
run.run(&mut info_run);
|
run.run(&mut info_run);
|
||||||
} else {
|
} else {
|
||||||
|
@ -6,7 +6,7 @@ pub fn assign(from: &Data, target: &Data) {
|
|||||||
.as_any()
|
.as_any()
|
||||||
.downcast_ref::<crate::data::reference::Reference>()
|
.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)) = (
|
} else if let (Some(from), Some(target)) = (
|
||||||
from.get()
|
from.get()
|
||||||
.as_any()
|
.as_any()
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Data, MersData, MersType, Type};
|
use super::{Data, MersData, MersType, Type};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Reference(pub Arc<Mutex<Data>>);
|
pub struct Reference(pub Arc<RwLock<Data>>);
|
||||||
|
|
||||||
impl MersData for Reference {
|
impl MersData for Reference {
|
||||||
fn is_eq(&self, other: &dyn MersData) -> bool {
|
fn is_eq(&self, other: &dyn MersData) -> bool {
|
||||||
if let Some(other) = other.as_any().downcast_ref::<Self>() {
|
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 {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ impl MersData for Reference {
|
|||||||
Box::new(Clone::clone(self))
|
Box::new(Clone::clone(self))
|
||||||
}
|
}
|
||||||
fn as_type(&self) -> Type {
|
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 {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
@ -69,7 +69,7 @@ impl MersType for ReferenceT {
|
|||||||
|
|
||||||
impl Display for Reference {
|
impl Display for Reference {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
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 {
|
impl Display for ReferenceT {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{Data, Type},
|
data::{Data, Type},
|
||||||
@ -69,7 +69,7 @@ impl Config {
|
|||||||
pub fn add_var(mut self, name: String, val: Data) -> Self {
|
pub fn add_var(mut self, name: String, val: Data) -> Self {
|
||||||
let t = val.get().as_type();
|
let t = val.get().as_type();
|
||||||
self.info_parsed.scopes[0].init_var(name, (0, self.globals));
|
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.info_check.scopes[0].init_var(self.globals, t);
|
||||||
self.globals += 1;
|
self.globals += 1;
|
||||||
self
|
self
|
||||||
|
@ -19,6 +19,7 @@ impl Config {
|
|||||||
/// `len: fn` gets the length of strings or tuples
|
/// `len: fn` gets the length of strings or tuples
|
||||||
/// `sleep: fn` sleeps for n seconds (pauses the current thread)
|
/// `sleep: fn` sleeps for n seconds (pauses the current thread)
|
||||||
/// `panic: fn` exits the program with the given exit code
|
/// `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 {
|
pub fn with_base(self) -> Self {
|
||||||
self.add_var("try".to_string(), Data::new(data::function::Function {
|
self.add_var("try".to_string(), Data::new(data::function::Function {
|
||||||
info: Arc::new(Info::neverused()),
|
info: Arc::new(Info::neverused()),
|
||||||
@ -112,6 +113,54 @@ impl Config {
|
|||||||
unreachable!("try: no function found")
|
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 {
|
.add_var("sleep".to_string(), Data::new(data::function::Function {
|
||||||
info: Arc::new(Info::neverused()),
|
info: Arc::new(Info::neverused()),
|
||||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||||
@ -268,7 +317,7 @@ impl Config {
|
|||||||
.as_any()
|
.as_any()
|
||||||
.downcast_ref::<data::reference::Reference>()
|
.downcast_ref::<data::reference::Reference>()
|
||||||
{
|
{
|
||||||
r.0.lock().unwrap().clone()
|
r.0.write().unwrap().clone()
|
||||||
} else {
|
} else {
|
||||||
unreachable!("called deref on non-reference")
|
unreachable!("called deref on non-reference")
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ impl Config {
|
|||||||
.downcast_ref::<data::reference::Reference>()
|
.downcast_ref::<data::reference::Reference>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
.lock()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_mut()
|
.get_mut()
|
||||||
.mut_any()
|
.mut_any()
|
||||||
@ -118,7 +118,7 @@ impl Config {
|
|||||||
.downcast_ref::<data::reference::Reference>()
|
.downcast_ref::<data::reference::Reference>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
.lock()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_mut()
|
.get_mut()
|
||||||
.mut_any()
|
.mut_any()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
@ -240,7 +240,7 @@ pub type CheckInfo = info::Info<CheckLocal>;
|
|||||||
|
|
||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Default, Clone, Debug)]
|
||||||
pub struct Local {
|
pub struct Local {
|
||||||
vars: Vec<Arc<Mutex<Data>>>,
|
vars: Vec<Arc<RwLock<Data>>>,
|
||||||
}
|
}
|
||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Default, Clone, Debug)]
|
||||||
pub struct CheckLocal {
|
pub struct CheckLocal {
|
||||||
@ -248,9 +248,9 @@ pub struct CheckLocal {
|
|||||||
}
|
}
|
||||||
impl info::Local for Local {
|
impl info::Local for Local {
|
||||||
type VariableIdentifier = usize;
|
type VariableIdentifier = usize;
|
||||||
type VariableData = Arc<Mutex<Data>>;
|
type VariableData = Arc<RwLock<Data>>;
|
||||||
fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) {
|
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 {
|
while self.vars.len() <= id {
|
||||||
self.vars.push(Arc::clone(¬hing));
|
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};
|
use crate::data::{self, Data, Type};
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ impl MersStatement for Variable {
|
|||||||
}
|
}
|
||||||
fn run_custom(&self, info: &mut super::Info) -> Data {
|
fn run_custom(&self, info: &mut super::Info) -> Data {
|
||||||
if self.is_init {
|
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 {
|
while info.scopes[self.var.0].vars.len() <= self.var.1 {
|
||||||
info.scopes[self.var.0].vars.push(Arc::clone(¬hing));
|
info.scopes[self.var.0].vars.push(Arc::clone(¬hing));
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ impl MersStatement for Variable {
|
|||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
info.scopes[self.var.0].vars[self.var.1]
|
info.scopes[self.var.0].vars[self.var.1]
|
||||||
.lock()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user