Encapsulate RwLock and RefCell into Locked.

This commit is contained in:
Stephen Chung 2020-10-16 23:41:56 +08:00
parent d88adfd73d
commit a16fc71935
3 changed files with 39 additions and 43 deletions

View File

@ -5,7 +5,7 @@ use crate::parser::{ImmutableString, INT};
use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast}; use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast};
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
use crate::fn_native::{shared_try_take, Shared}; use crate::fn_native::{shared_try_take, Locked, Shared};
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
use crate::parser::FLOAT; use crate::parser::FLOAT;
@ -26,14 +26,11 @@ use crate::stdlib::{
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
use crate::stdlib::{ use crate::stdlib::cell::{Ref, RefMut};
cell::{Ref, RefCell, RefMut},
rc::Rc,
};
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
use crate::stdlib::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; use crate::stdlib::sync::{RwLockReadGuard, RwLockWriteGuard};
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
use crate::stdlib::collections::HashMap; use crate::stdlib::collections::HashMap;
@ -165,11 +162,7 @@ pub enum Union {
Variant(Box<Box<dyn Variant>>), Variant(Box<Box<dyn Variant>>),
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "sync"))] Shared(Shared<Locked<Dynamic>>),
Shared(Shared<RefCell<Dynamic>>),
#[cfg(not(feature = "no_closure"))]
#[cfg(feature = "sync")]
Shared(Shared<RwLock<Dynamic>>),
} }
/// Underlying `Variant` read guard for `Dynamic`. /// Underlying `Variant` read guard for `Dynamic`.
@ -644,10 +637,7 @@ impl Dynamic {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
return match self.0 { return match self.0 {
Union::Shared(..) => self, Union::Shared(..) => self,
#[cfg(not(feature = "sync"))] _ => Self(Union::Shared(Locked::new(self).into())),
_ => Self(Union::Shared(Rc::new(RefCell::new(self)))),
#[cfg(feature = "sync")]
_ => Self(Union::Shared(Arc::new(RwLock::new(self)))),
}; };
#[cfg(feature = "no_closure")] #[cfg(feature = "no_closure")]
@ -859,15 +849,20 @@ impl Dynamic {
pub fn flatten(self) -> Self { pub fn flatten(self) -> Self {
match self.0 { match self.0 {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(cell) => { Union::Shared(cell) => shared_try_take(cell).map_or_else(
|cell| {
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
return shared_try_take(cell) return cell.borrow().clone();
.map_or_else(|c| c.borrow().clone(), RefCell::into_inner);
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
return shared_try_take(cell) return cell.read().unwrap().clone();
.map_or_else(|c| c.read().unwrap().clone(), |v| v.into_inner().unwrap()); },
} |value| {
#[cfg(not(feature = "sync"))]
return value.into_inner();
#[cfg(feature = "sync")]
return value.into_inner().unwrap();
},
),
_ => self, _ => self,
} }
} }
@ -910,7 +905,6 @@ impl Dynamic {
Union::Shared(ref cell) => { Union::Shared(ref cell) => {
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
let data = cell.borrow(); let data = cell.borrow();
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
let data = cell.read().unwrap(); let data = cell.read().unwrap();
@ -944,7 +938,6 @@ impl Dynamic {
Union::Shared(ref cell) => { Union::Shared(ref cell) => {
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
let data = cell.borrow_mut(); let data = cell.borrow_mut();
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
let data = cell.write().unwrap(); let data = cell.write().unwrap();

View File

@ -15,10 +15,10 @@ use crate::stdlib::{
boxed::Box, convert::TryFrom, fmt, iter::empty, mem, string::String, vec::Vec, boxed::Box, convert::TryFrom, fmt, iter::empty, mem, string::String, vec::Vec,
}; };
#[cfg(not(feature = "sync"))]
use crate::stdlib::rc::Rc;
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
use crate::stdlib::sync::Arc; use crate::stdlib::sync::{Arc, RwLock};
#[cfg(not(feature = "sync"))]
use crate::stdlib::{cell::RefCell, rc::Rc};
/// Trait that maps to `Send + Sync` only under the `sync` feature. /// Trait that maps to `Send + Sync` only under the `sync` feature.
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
@ -34,13 +34,20 @@ pub trait SendSync {}
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
impl<T> SendSync for T {} impl<T> SendSync for T {}
/// Immutable reference-counted container /// Immutable reference-counted container.
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
pub type Shared<T> = Rc<T>; pub type Shared<T> = Rc<T>;
/// Immutable reference-counted container /// Immutable reference-counted container.
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
pub type Shared<T> = Arc<T>; pub type Shared<T> = Arc<T>;
/// Synchronized shared object.
#[cfg(not(feature = "sync"))]
pub type Locked<T> = RefCell<T>;
/// Synchronized shared object.
#[cfg(feature = "sync")]
pub type Locked<T> = RwLock<T>;
/// Consume a `Shared` resource and return a mutable reference to the wrapped value. /// Consume a `Shared` resource and return a mutable reference to the wrapped value.
/// If the resource is shared (i.e. has other outstanding references), a cloned copy is used. /// If the resource is shared (i.e. has other outstanding references), a cloned copy is used.
pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T { pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T {

View File

@ -1,4 +1,5 @@
use crate::engine::Engine; use crate::engine::Engine;
use crate::fn_native::Locked;
use crate::module::{Module, ModuleResolver}; use crate::module::{Module, ModuleResolver};
use crate::parser::AST; use crate::parser::AST;
use crate::result::EvalAltResult; use crate::result::EvalAltResult;
@ -6,12 +7,6 @@ use crate::token::Position;
use crate::stdlib::{boxed::Box, collections::HashMap, path::PathBuf, string::String}; use crate::stdlib::{boxed::Box, collections::HashMap, path::PathBuf, string::String};
#[cfg(not(feature = "sync"))]
use crate::stdlib::cell::RefCell;
#[cfg(feature = "sync")]
use crate::stdlib::sync::RwLock;
/// Module resolution service that loads module script files from the file system. /// Module resolution service that loads module script files from the file system.
/// ///
/// Script files are cached so they are are not reloaded and recompiled in subsequent requests. /// Script files are cached so they are are not reloaded and recompiled in subsequent requests.
@ -21,6 +16,12 @@ use crate::stdlib::sync::RwLock;
/// to the base directory. The script file is then forced to be in a specified extension /// to the base directory. The script file is then forced to be in a specified extension
/// (default `.rhai`). /// (default `.rhai`).
/// ///
/// # Function Namespace
///
/// When a function within a script file module is loaded, all functions in the _global_ namespace
/// plus all those defined within the same module are _merged_ into a _unified_ namespace before
/// the call. Therefore, functions in a module script can cross-call each other.
///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
@ -39,12 +40,7 @@ use crate::stdlib::sync::RwLock;
pub struct FileModuleResolver { pub struct FileModuleResolver {
path: PathBuf, path: PathBuf,
extension: String, extension: String,
cache: Locked<HashMap<PathBuf, AST>>,
#[cfg(not(feature = "sync"))]
cache: RefCell<HashMap<PathBuf, AST>>,
#[cfg(feature = "sync")]
cache: RwLock<HashMap<PathBuf, AST>>,
} }
impl Default for FileModuleResolver { impl Default for FileModuleResolver {