More work on switching battle data to interior mutability, instead of exterior mutability.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -56,12 +56,13 @@ macro_rules! run_scripts {
|
||||
}
|
||||
}
|
||||
ScriptWrapper::Set(s) => {
|
||||
if let Some(s) = s.upgrade() {
|
||||
for s in s.read().get_underlying() {
|
||||
if let Some(s) = s.1.get() {
|
||||
if let Some(set) = s.upgrade() {
|
||||
let current_scripts = set.get_owning_iterator();
|
||||
for s in current_scripts {
|
||||
if let Some(s) = s.get() {
|
||||
let s = s.read();
|
||||
if let Some(s) = s.deref() {
|
||||
if !s.is_suppressed() {
|
||||
if !s.is_suppressed() && set.has(s.name()) {
|
||||
s.$hook_name($($parameters),*);
|
||||
}
|
||||
}
|
||||
@@ -100,7 +101,7 @@ pub trait ScriptSource<'a> {
|
||||
#[derive(Debug)]
|
||||
pub enum ScriptWrapper {
|
||||
Script(Weak<RwLock<Option<Arc<dyn Script>>>>),
|
||||
Set(Weak<RwLock<ScriptSet>>),
|
||||
Set(Weak<ScriptSet>),
|
||||
}
|
||||
|
||||
impl From<&ScriptContainer> for ScriptWrapper {
|
||||
@@ -109,8 +110,8 @@ impl From<&ScriptContainer> for ScriptWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Arc<RwLock<ScriptSet>>> for ScriptWrapper {
|
||||
fn from(c: &Arc<RwLock<ScriptSet>>) -> Self {
|
||||
impl From<&Arc<ScriptSet>> for ScriptWrapper {
|
||||
fn from(c: &Arc<ScriptSet>) -> Self {
|
||||
ScriptWrapper::Set(Arc::downgrade(c))
|
||||
}
|
||||
}
|
||||
@@ -141,7 +142,7 @@ impl ScriptAggregator {
|
||||
if let ScriptWrapper::Set(set) = wrapper {
|
||||
if let Some(set) = set.upgrade() {
|
||||
self.set_index += 1;
|
||||
if self.set_index as usize >= set.read().count() {
|
||||
if self.set_index as usize >= set.count() {
|
||||
self.set_index = -1;
|
||||
} else {
|
||||
return true;
|
||||
@@ -155,7 +156,7 @@ impl ScriptAggregator {
|
||||
let wrapper = unsafe { &self.scripts.as_ref().unwrap()[self.index as usize] };
|
||||
if let ScriptWrapper::Set(s) = wrapper {
|
||||
if let Some(set) = s.upgrade() {
|
||||
if set.read().count() > 0 {
|
||||
if set.count() > 0 {
|
||||
self.set_index = 0;
|
||||
return true;
|
||||
}
|
||||
@@ -181,9 +182,8 @@ impl ScriptAggregator {
|
||||
// increment_to_next_value
|
||||
ScriptWrapper::Script(script) => Some(script.upgrade().unwrap().into()),
|
||||
ScriptWrapper::Set(set) => {
|
||||
let lock = set.as_ptr().as_ref().unwrap();
|
||||
let l = lock.read();
|
||||
let sc = l.at(self.set_index as usize);
|
||||
let set = set.upgrade().unwrap();
|
||||
let sc = set.at(self.set_index as usize);
|
||||
return Some(sc.clone());
|
||||
}
|
||||
};
|
||||
@@ -337,13 +337,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn script_aggregator_property_iterates_script_set() {
|
||||
let set = Arc::new(RwLock::new(ScriptSet::default()));
|
||||
let mut mut_set = set.write();
|
||||
mut_set.add(Arc::new(TestScript::new_with_name("test_a")));
|
||||
mut_set.add(Arc::new(TestScript::new_with_name("test_b")));
|
||||
mut_set.add(Arc::new(TestScript::new_with_name("test_c")));
|
||||
// Drop so we don't have a lock on it anymore.
|
||||
drop(mut_set);
|
||||
let set = Arc::new(ScriptSet::default());
|
||||
set.add(Arc::new(TestScript::new_with_name("test_a")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_b")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_c")));
|
||||
|
||||
let scripts = vec![ScriptWrapper::from(&set)];
|
||||
let mut aggregator = ScriptAggregator::new(&scripts as *const Vec<ScriptWrapper>);
|
||||
@@ -352,14 +349,16 @@ mod tests {
|
||||
while let Some(v) = aggregator.get_next() {
|
||||
v.get().unwrap().read().as_ref().unwrap().on_initialize(&[]);
|
||||
}
|
||||
let set = set.read();
|
||||
let s = set.at(0).get_as::<TestScript>();
|
||||
let s = set.at(0);
|
||||
let s = s.get_as::<TestScript>();
|
||||
assert_eq!(s.test_count.load(Ordering::Relaxed), i);
|
||||
assert_eq!(s.name().str(), "test_a");
|
||||
let s = set.at(1).get_as::<TestScript>();
|
||||
let s = set.at(1);
|
||||
let s = s.get_as::<TestScript>();
|
||||
assert_eq!(s.test_count.load(Ordering::Relaxed), i);
|
||||
assert_eq!(s.name().str(), "test_b");
|
||||
let s = set.at(2).get_as::<TestScript>();
|
||||
let s = set.at(2);
|
||||
let s = s.get_as::<TestScript>();
|
||||
assert_eq!(s.test_count.load(Ordering::Relaxed), i);
|
||||
assert_eq!(s.name().str(), "test_c");
|
||||
}
|
||||
@@ -367,13 +366,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn script_aggregator_property_iterates_script_set_when_removing_last() {
|
||||
let set = Arc::new(RwLock::new(ScriptSet::default()));
|
||||
let mut mut_set = set.write();
|
||||
mut_set.add(Arc::new(TestScript::new_with_name("test_a")));
|
||||
mut_set.add(Arc::new(TestScript::new_with_name("test_b")));
|
||||
mut_set.add(Arc::new(TestScript::new_with_name("test_c")));
|
||||
// Drop so we don't have a lock on it anymore.
|
||||
drop(mut_set);
|
||||
let set = Arc::new(ScriptSet::default());
|
||||
set.add(Arc::new(TestScript::new_with_name("test_a")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_b")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_c")));
|
||||
|
||||
let scripts = vec![ScriptWrapper::from(&set)];
|
||||
let mut aggregator = ScriptAggregator::new(&scripts as *const Vec<ScriptWrapper>);
|
||||
@@ -404,22 +400,16 @@ mod tests {
|
||||
"test_b"
|
||||
);
|
||||
|
||||
let mut mut_set = set.write();
|
||||
mut_set.remove(&StringKey::new("test_c"));
|
||||
drop(mut_set);
|
||||
|
||||
set.remove(&StringKey::new("test_c"));
|
||||
assert!(aggregator.get_next().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn script_aggregator_property_iterates_script_set_when_removing_middle() {
|
||||
let set = Arc::new(RwLock::new(ScriptSet::default()));
|
||||
let mut mut_set = set.write();
|
||||
mut_set.add(Arc::new(TestScript::new_with_name("test_a")));
|
||||
mut_set.add(Arc::new(TestScript::new_with_name("test_b")));
|
||||
mut_set.add(Arc::new(TestScript::new_with_name("test_c")));
|
||||
// Drop so we don't have a lock on it anymore.
|
||||
drop(mut_set);
|
||||
let set = Arc::new(ScriptSet::default());
|
||||
set.add(Arc::new(TestScript::new_with_name("test_a")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_b")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_c")));
|
||||
|
||||
let scripts = vec![ScriptWrapper::from(&set)];
|
||||
let mut aggregator = ScriptAggregator::new(&scripts as *const Vec<ScriptWrapper>);
|
||||
@@ -437,9 +427,7 @@ mod tests {
|
||||
"test_a"
|
||||
);
|
||||
|
||||
let mut mut_set = set.write();
|
||||
mut_set.remove(&StringKey::new("test_b"));
|
||||
drop(mut_set);
|
||||
set.remove(&StringKey::new("test_b"));
|
||||
|
||||
assert_eq!(
|
||||
aggregator
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
use crate::dynamic_data::script_handling::script::{Script, ScriptContainer};
|
||||
use crate::{PkmnResult, StringKey};
|
||||
use indexmap::IndexMap;
|
||||
use parking_lot::RwLock;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ScriptSet {
|
||||
scripts: IndexMap<StringKey, ScriptContainer>,
|
||||
scripts: RwLock<IndexMap<StringKey, ScriptContainer>>,
|
||||
}
|
||||
|
||||
impl ScriptSet {
|
||||
pub fn add(&mut self, script: Arc<dyn Script>) -> ScriptContainer {
|
||||
if let Some(lock) = self.scripts.get(script.name()) {
|
||||
pub fn add(&self, script: Arc<dyn Script>) -> ScriptContainer {
|
||||
if let Some(lock) = self.scripts.read().get(script.name()) {
|
||||
if let Some(existing) = lock.get() {
|
||||
let existing = existing.read();
|
||||
if let Some(v) = &*existing {
|
||||
@@ -19,15 +21,17 @@ impl ScriptSet {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.scripts.insert(script.name().clone(), ScriptContainer::new(script));
|
||||
self.scripts.last().unwrap().1.clone()
|
||||
self.scripts
|
||||
.write()
|
||||
.insert(script.name().clone(), ScriptContainer::new(script));
|
||||
self.scripts.read().last().unwrap().1.clone()
|
||||
}
|
||||
|
||||
pub fn stack_or_add<'b, F>(&mut self, key: &StringKey, instantiation: &'b F) -> PkmnResult<Option<ScriptContainer>>
|
||||
pub fn stack_or_add<'b, F>(&self, key: &StringKey, instantiation: &'b F) -> PkmnResult<Option<ScriptContainer>>
|
||||
where
|
||||
F: Fn() -> PkmnResult<Option<Arc<dyn Script>>>,
|
||||
{
|
||||
if let Some(lock) = self.scripts.get(key) {
|
||||
if let Some(lock) = self.scripts.read().get(key) {
|
||||
if let Some(existing) = lock.get() {
|
||||
let existing = existing.read();
|
||||
if let Some(v) = &*existing {
|
||||
@@ -40,19 +44,19 @@ impl ScriptSet {
|
||||
if let Some(script) = script {
|
||||
let name = script.name().clone();
|
||||
let arc = ScriptContainer::new(script);
|
||||
self.scripts.insert(name, arc);
|
||||
Ok(Some(self.scripts.last().unwrap().1.clone()))
|
||||
self.scripts.write().insert(name, arc);
|
||||
Ok(Some(self.scripts.read().last().unwrap().1.clone()))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &StringKey) -> Option<&ScriptContainer> {
|
||||
self.scripts.get(key)
|
||||
pub fn get(&self, key: &StringKey) -> Option<ScriptContainer> {
|
||||
self.scripts.read().get(key).cloned()
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, key: &StringKey) {
|
||||
let value = self.scripts.shift_remove(key);
|
||||
pub fn remove(&self, key: &StringKey) {
|
||||
let value = self.scripts.write().shift_remove(key);
|
||||
if let Some(script) = value {
|
||||
if let Some(script) = script.get() {
|
||||
let script = script.read();
|
||||
@@ -62,30 +66,35 @@ impl ScriptSet {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
for script in &self.scripts {
|
||||
pub fn clear(&self) {
|
||||
for script in self.scripts.read().deref() {
|
||||
if let Some(script) = script.1.get() {
|
||||
let script = script.read();
|
||||
script.as_ref().unwrap().on_remove();
|
||||
script.as_ref().unwrap().mark_for_deletion();
|
||||
}
|
||||
}
|
||||
self.scripts.clear();
|
||||
self.scripts.write().clear();
|
||||
}
|
||||
|
||||
pub fn has(&self, key: &StringKey) -> bool {
|
||||
self.scripts.contains_key(key)
|
||||
self.scripts.read().contains_key(key)
|
||||
}
|
||||
|
||||
pub fn at(&self, index: usize) -> &ScriptContainer {
|
||||
&self.scripts[index]
|
||||
pub fn at(&self, index: usize) -> ScriptContainer {
|
||||
self.scripts.read()[index].clone()
|
||||
}
|
||||
|
||||
pub fn count(&self) -> usize {
|
||||
self.scripts.len()
|
||||
self.scripts.read().len()
|
||||
}
|
||||
|
||||
pub(crate) fn get_underlying(&self) -> &IndexMap<StringKey, ScriptContainer> {
|
||||
&self.scripts
|
||||
pub(crate) fn get_owning_iterator(&self) -> Vec<ScriptContainer> {
|
||||
let s = self.scripts.read();
|
||||
let mut v = Vec::with_capacity(s.deref().len());
|
||||
for script in s.deref().values() {
|
||||
v.push(script.clone());
|
||||
}
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,26 @@
|
||||
use crate::dynamic_data::script_handling::script::{Script, ScriptContainer};
|
||||
use crate::dynamic_data::script_handling::script_set::ScriptSet;
|
||||
use crate::{PkmnResult, StringKey};
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait VolatileScripts<'a> {
|
||||
fn volatile_scripts(&self) -> &Arc<RwLock<ScriptSet>>;
|
||||
fn volatile_scripts(&self) -> &Arc<ScriptSet>;
|
||||
fn load_volatile_script(&self, key: &StringKey) -> PkmnResult<Option<Arc<dyn Script>>>;
|
||||
|
||||
fn has_volatile_script(&self, key: &StringKey) -> bool {
|
||||
self.volatile_scripts().read().has(key)
|
||||
self.volatile_scripts().has(key)
|
||||
}
|
||||
|
||||
fn get_volatile_script(&self, key: &StringKey) -> Option<ScriptContainer> {
|
||||
let scripts = self.volatile_scripts().read();
|
||||
let s = scripts.get(key);
|
||||
s.cloned()
|
||||
self.volatile_scripts().get(key)
|
||||
}
|
||||
|
||||
fn add_volatile_script(&mut self, key: &StringKey) -> PkmnResult<Option<ScriptContainer>> {
|
||||
self.volatile_scripts()
|
||||
.write()
|
||||
.stack_or_add(key, &|| self.load_volatile_script(key))
|
||||
}
|
||||
|
||||
fn remove_volatile_script(&mut self, key: &StringKey) {
|
||||
self.volatile_scripts().write().remove(key)
|
||||
self.volatile_scripts().remove(key)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user