use crate::storage::collection::Collections as AssetCollections;
use kanal::{Receiver, Sender, bounded};
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use std::{
collections::HashMap,
ops::{Deref, DerefMut},
sync::atomic::AtomicUsize,
};
static CURRENT: Lazy<Mutex<AssetCollections>> =
Lazy::new(|| Mutex::new(AssetCollections::default()));
static COLLECTION_ID: AtomicUsize = AtomicUsize::new(0);
static SENDERS: Lazy<Mutex<HashMap<usize, Sender<AssetCollections>>>> =
Lazy::new(|| Mutex::new(HashMap::new()));
pub(crate) struct Collections {
id: usize,
receiver: Receiver<AssetCollections>,
current: AssetCollections,
generation: u64,
}
impl std::fmt::Debug for Collections {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Collections").finish_non_exhaustive()
}
}
impl Default for Collections {
fn default() -> Self {
let (sender, receiver) = bounded(8);
let id = COLLECTION_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
SENDERS.lock().insert(id, sender);
Self {
id,
receiver,
current: CURRENT.lock().clone(),
generation: 0,
}
}
}
impl Drop for Collections {
fn drop(&mut self) {
SENDERS.lock().remove(&self.id);
}
}
impl Deref for Collections {
type Target = AssetCollections;
fn deref(&self) -> &Self::Target {
&self.current
}
}
impl DerefMut for Collections {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.current
}
}
impl Collections {
#[cfg_attr(feature = "profiling", profiling::function)]
pub(crate) fn update(&mut self) {
while let Ok(Some(new_collections)) = self.receiver.try_recv() {
self.current = new_collections;
self.generation += 1;
}
}
pub(crate) fn generation(&self) -> u64 {
self.generation
}
pub(crate) fn save(&mut self) {
self.generation += 1;
for (id, sender) in SENDERS.lock().iter() {
if id == &self.id {
continue;
}
sender
.send(self.current.clone())
.expect("Could not send collections");
}
CURRENT.lock().clone_from(&self.current);
}
}