use VK_NULL_HANDLE; use std::{borrow, cmp, fmt, ops}; #[cfg(feature = "nightly")] use std::collections::HashMap; #[cfg(feature = "nightly")] use std::sync::{Arc, Mutex}; #[cfg(feature = "nightly")] lazy_static! { static ref REGISTRY: Arc>> = Arc::new(Mutex::new(HashMap::new())); } #[repr(C)] pub struct Handle(*mut T); #[cfg(feature = "nightly")] impl Handle<()> { pub fn report_leaks() { println!("Leaked handles:"); let mut map = REGISTRY.lock().unwrap(); for (_, type_id) in map.drain() { println!("\t{:?}", type_id); } } } impl Handle { pub fn new(value: T) -> Self { let ptr = Box::into_raw(Box::new(value)); #[cfg(feature = "nightly")] { use std::intrinsics::type_name; let name = unsafe { type_name::() }; REGISTRY.lock().unwrap().insert(ptr as _, name); } Handle(ptr) } pub fn null() -> Self { Handle(VK_NULL_HANDLE as *mut _) } pub fn unbox(self) -> Option { if self.0 == VK_NULL_HANDLE as *mut T { None } else { #[cfg(feature = "nightly")] { REGISTRY.lock().unwrap().remove(&(self.0 as _)).unwrap(); } Some(*unsafe { Box::from_raw(self.0) }) } } pub fn as_ref(&self) -> Option<&T> { if self.0 == VK_NULL_HANDLE as *mut T { None } else { Some(unsafe { &*self.0 }) } } } impl Clone for Handle { fn clone(&self) -> Self { Handle(self.0) } } impl Copy for Handle {} impl ops::Deref for Handle { type Target = T; fn deref(&self) -> &T { unsafe { &*self.0 } } } impl ops::DerefMut for Handle { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.0 } } } impl borrow::Borrow for Handle { fn borrow(&self) -> &T { unsafe { &*self.0 } } } impl cmp::PartialEq for Handle { fn eq(&self, other: &Self) -> bool { self.0.eq(&other.0) } } impl fmt::Debug for Handle { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "Handle({:p})", self.0) } } #[cfg(feature = "dispatch")] pub use self::dispatch::DispatchHandle; #[cfg(not(feature = "dispatch"))] pub type DispatchHandle = Handle; #[cfg(feature = "dispatch")] mod dispatch { use VK_NULL_HANDLE; use std::{borrow, cmp, fmt, ops}; const ICD_LOADER_MAGIC: u64 = 0x01CDC0DE; #[repr(C)] pub struct DispatchHandle(*mut (u64, T)); impl DispatchHandle { pub fn new(value: T) -> Self { let ptr = Box::into_raw(Box::new((ICD_LOADER_MAGIC, value))); DispatchHandle(ptr) } pub fn null() -> Self { DispatchHandle(VK_NULL_HANDLE as *mut _) } pub fn unbox(self) -> Option { if self.0 == VK_NULL_HANDLE as *mut (u64, T) { None } else { Some(unsafe { Box::from_raw(self.0) }.1) } } pub fn as_ref(&self) -> Option<&T> { if self.0 == VK_NULL_HANDLE as *mut (u64, T) { None } else { Some(unsafe { &(*self.0).1 }) } } } impl Clone for DispatchHandle { fn clone(&self) -> Self { DispatchHandle(self.0) } } impl Copy for DispatchHandle {} impl ops::Deref for DispatchHandle { type Target = T; fn deref(&self) -> &T { unsafe { &(*self.0).1 } } } impl ops::DerefMut for DispatchHandle { fn deref_mut(&mut self) -> &mut T { unsafe { &mut (*self.0).1 } } } impl borrow::Borrow for DispatchHandle { fn borrow(&self) -> &T { unsafe { &(*self.0).1 } } } impl cmp::PartialEq for DispatchHandle { fn eq(&self, other: &Self) -> bool { self.0.eq(&other.0) } } impl fmt::Debug for DispatchHandle { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "DispatchHandle({:p})", self.0) } } }