use core::any::{Any, TypeId};
use core::fmt;
use core::marker::PhantomData;
use core::ops::Deref;
use std::collections::HashMap;
use std::sync::Arc;
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
#[derive(Default, Debug)]
pub struct GenericGlobal(RwLock<HashMap<TypeId, Arc<dyn Any>>>);
impl GenericGlobal {
pub fn new() -> Self {
Self::default()
}
pub fn get_or_init<T: 'static + Send + Sync>(&self, f: impl FnOnce() -> T) -> Entry<T> {
let typeid = TypeId::of::<T>();
if let Some(val) = self.0.read().get(&typeid) {
return Entry::new(Arc::clone(val));
}
let guard = self.0.upgradable_read();
if let Some(val) = guard.get(&typeid) {
return Entry::new(Arc::clone(val));
}
let mut guard = RwLockUpgradableReadGuard::upgrade(guard);
let arc: Arc<dyn Any> = Arc::new(f());
let option = guard.insert(typeid, Arc::clone(&arc));
debug_assert!(option.is_none());
Entry::new(arc)
}
}
unsafe impl Send for GenericGlobal {}
unsafe impl Sync for GenericGlobal {}
#[derive(Debug)]
pub struct Entry<T: 'static>(Arc<dyn Any>, PhantomData<T>);
unsafe impl<T: 'static + Send + Sync> Send for Entry<T> {}
unsafe impl<T: 'static + Send + Sync> Sync for Entry<T> {}
impl<T: 'static> Clone for Entry<T> {
fn clone(&self) -> Self {
Self::new(self.0.clone())
}
}
impl<T: 'static> Entry<T> {
fn new(arc: Arc<dyn Any>) -> Self {
Self(arc, PhantomData)
}
}
impl<T: 'static> Deref for Entry<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
<dyn Any>::downcast_ref::<T>(&*self.0).unwrap()
}
}
impl<T: 'static + fmt::Display> fmt::Display for Entry<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.deref(), f)
}
}
impl<T: 'static> fmt::Pointer for Entry<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.0, f)
}
}
#[cfg(test)]
mod tests {}