macro_rules! component { ($name:ident : $inner:ident { $($key:ident : $ty:ty = $value:expr,)* }) => { #[derive(Clone)] pub struct $name(::std::sync::Arc<($crate::session::SessionWeak, ::std::sync::Mutex<$inner>)>); impl $name { #[allow(dead_code)] pub fn new(session: $crate::session::SessionWeak) -> $name { $name(::std::sync::Arc::new((session, ::std::sync::Mutex::new($inner { $($key : $value,)* })))) } #[allow(dead_code)] fn lock R, R>(&self, f: F) -> R { let mut inner = (self.0).1.lock().expect("Mutex poisoned"); f(&mut inner) } #[allow(dead_code)] fn session(&self) -> $crate::session::Session { (self.0).0.upgrade() } } struct $inner { $($key : $ty,)* } } } use std::sync::Mutex; use std::cell::UnsafeCell; pub struct Lazy(Mutex, UnsafeCell>); unsafe impl Sync for Lazy {} unsafe impl Send for Lazy {} impl Lazy { pub fn new() -> Lazy { Lazy(Mutex::new(false), UnsafeCell::new(None)) } pub fn get T>(&self, f: F) -> &T { let mut inner = self.0.lock().unwrap(); if !*inner { unsafe { *self.1.get() = Some(f()); } *inner = true; } unsafe { &*self.1.get() }.as_ref().unwrap() } }