More work on switching battle data to interior mutability, instead of exterior mutability.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2022-06-19 12:07:54 +02:00
parent 2e19005a30
commit 715f16e2b8
14 changed files with 256 additions and 280 deletions

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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)
}
}