From f0d7f7499f4621101bd30901c406bcf744016e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20H=C3=B6lting?= <87192362+moritz-hoelting@users.noreply.github.com> Date: Tue, 2 Apr 2024 17:10:57 +0200 Subject: [PATCH] Add ExtendableQueue utility and refactor code --- src/datapack/namespace.rs | 26 ++++-------- src/util/compile.rs | 17 +++----- src/util/extendable_queue.rs | 82 ++++++++++++++++++++++++++++++++++++ src/util/mod.rs | 1 + 4 files changed, 96 insertions(+), 30 deletions(-) create mode 100644 src/util/extendable_queue.rs diff --git a/src/datapack/namespace.rs b/src/datapack/namespace.rs index 36a384e..bc79c90 100644 --- a/src/datapack/namespace.rs +++ b/src/datapack/namespace.rs @@ -3,15 +3,15 @@ use serde::{Deserialize, Serialize}; use crate::{ - util::compile::{CompileOptions, FunctionCompilerState, MutCompilerState}, + util::{ + compile::{CompileOptions, FunctionCompilerState, MutCompilerState}, + extendable_queue::ExtendableQueue, + }, virtual_fs::VFolder, }; use super::{function::Function, tag::Tag}; -use std::{ - collections::{HashMap, VecDeque}, - sync::{Arc, Mutex}, -}; +use std::collections::{HashMap, VecDeque}; /// Namespace of a datapack #[derive(Debug, Clone, Serialize, Deserialize)] @@ -89,20 +89,10 @@ impl Namespace { functions.push_front(("main".to_string(), self.main_function.clone())); } - let functions = Arc::new(Mutex::new(functions)); + let mut functions = ExtendableQueue::from(functions); - loop { - let Some((path, function)) = ({ - let mut functions = functions.lock().unwrap(); - let entry = functions.pop_front(); - drop(functions); - entry - }) else { - break; - }; - - let function_state = - FunctionCompilerState::new(&path, &self.name, Arc::downgrade(&functions)); + while let Some((path, function)) = functions.next() { + let function_state = FunctionCompilerState::new(&path, &self.name, functions.clone()); root_folder.add_file( &format!("functions/{}.mcfunction", path), function.compile(options, state, &function_state), diff --git a/src/util/compile.rs b/src/util/compile.rs index 0336afb..7d76d18 100644 --- a/src/util/compile.rs +++ b/src/util/compile.rs @@ -1,16 +1,14 @@ //! Compile options for the compiler. -use std::{ - cell::Cell, - collections::VecDeque, - sync::{Mutex, Weak}, -}; +use std::{cell::Cell, sync::Mutex}; use getset::Getters; use serde::{Deserialize, Serialize}; use crate::datapack::Function; +use super::extendable_queue::ExtendableQueue; + /// Compile options for the compiler. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CompileOptions { @@ -46,7 +44,7 @@ pub struct FunctionCompilerState { functions: FunctionQueue, } -type FunctionQueue = Weak>>; +type FunctionQueue = ExtendableQueue<(String, Function)>; impl FunctionCompilerState { /// Create a new function compiler state. @@ -61,11 +59,6 @@ impl FunctionCompilerState { /// Add a function to the queue. pub fn add_function(&self, name: &str, function: Function) { - if let Some(queue) = self.functions.upgrade() { - queue - .lock() - .unwrap() - .push_back((name.to_string(), function)); - } + self.functions.push((name.to_string(), function)); } } diff --git a/src/util/extendable_queue.rs b/src/util/extendable_queue.rs new file mode 100644 index 0000000..bdda66b --- /dev/null +++ b/src/util/extendable_queue.rs @@ -0,0 +1,82 @@ +//! A queue that can be extended while iterating over it. + +use std::{ + collections::VecDeque, + sync::{Arc, RwLock, Weak}, +}; + +/// A queue that can be extended while iterating over it. +#[derive(Debug, Clone)] +pub struct ExtendableQueue { + queue: Arc>>, +} + +impl Default for ExtendableQueue { + fn default() -> Self { + Self { + queue: Arc::new(RwLock::new(VecDeque::new())), + } + } +} + +impl From for ExtendableQueue +where + V: Into>, +{ + fn from(value: V) -> Self { + Self { + queue: Arc::new(RwLock::new(value.into())), + } + } +} + +impl ExtendableQueue { + /// Add an element to the queue. + pub fn push(&self, value: T) { + self.queue.write().unwrap().push_back(value); + } + + /// Get the queue. + pub fn get(&self) -> &Arc>> { + &self.queue + } + + /// Get a weak reference to the queue. + pub fn get_weak(&self) -> Weak>> { + Arc::downgrade(&self.queue) + } + + /// Clear the queue. + pub fn clear(&self) { + self.queue.write().unwrap().clear(); + } + + /// Get the length of the queue. + pub fn len(&self) -> usize { + self.queue.read().unwrap().len() + } + + /// Check if the queue is empty. + pub fn is_empty(&self) -> bool { + self.queue.read().unwrap().is_empty() + } + + /// Get and remove the next item without needing mutable access. + pub fn pop_front(&self) -> Option { + self.queue.write().unwrap().pop_front() + } +} + +impl Extend for ExtendableQueue { + fn extend>(&mut self, iter: T) { + self.queue.write().unwrap().extend(iter); + } +} + +impl Iterator for ExtendableQueue { + type Item = T; + + fn next(&mut self) -> Option { + self.queue.write().unwrap().pop_front() + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 063a674..538f1c5 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,4 @@ //! Utility functions for the Shulkerbox project. pub mod compile; +pub mod extendable_queue;