portability/libportability-gfx/src/handle.rs

184 lines
4.3 KiB
Rust
Raw Normal View History

use VK_NULL_HANDLE;
use std::{borrow, cmp, fmt, ops};
2018-04-26 02:00:50 +10:00
#[cfg(feature = "nightly")]
use std::collections::HashMap;
#[cfg(feature = "nightly")]
use std::sync::{Arc, Mutex};
2017-09-07 11:34:41 +10:00
2018-04-26 02:00:50 +10:00
#[cfg(feature = "nightly")]
lazy_static! {
static ref REGISTRY: Arc<Mutex<HashMap<usize, &'static str>>> = Arc::new(Mutex::new(HashMap::new()));
}
2018-03-15 08:24:26 +11:00
2017-09-07 11:34:41 +10:00
#[repr(C)]
2017-11-14 14:55:43 +11:00
pub struct Handle<T>(*mut T);
2017-09-07 11:34:41 +10:00
2018-04-26 02:00:50 +10:00
#[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<T: 'static> Handle<T> {
2017-09-07 11:34:41 +10:00
pub fn new(value: T) -> Self {
2017-11-14 14:55:43 +11:00
let ptr = Box::into_raw(Box::new(value));
2018-04-26 02:00:50 +10:00
#[cfg(feature = "nightly")]
{
use std::intrinsics::type_name;
let name = unsafe { type_name::<T>() };
REGISTRY.lock().unwrap().insert(ptr as _, name);
}
2017-11-14 14:55:43 +11:00
Handle(ptr)
2017-09-07 11:34:41 +10:00
}
pub fn null() -> Self {
Handle(VK_NULL_HANDLE as *mut _)
}
2018-04-19 09:11:32 +10:00
pub fn unbox(self) -> Option<T> {
if self.0 == VK_NULL_HANDLE as *mut T {
None
} else {
2018-04-26 02:00:50 +10:00
#[cfg(feature = "nightly")]
{
REGISTRY.lock().unwrap().remove(&(self.0 as _)).unwrap();
}
2018-04-19 09:11:32 +10:00
Some(*unsafe { Box::from_raw(self.0) })
}
2017-09-07 11:34:41 +10:00
}
2018-04-19 09:11:32 +10:00
pub fn as_ref(&self) -> Option<&T> {
if self.0 == VK_NULL_HANDLE as *mut T {
None
} else {
Some(unsafe { &*self.0 })
}
}
2017-09-07 11:34:41 +10:00
}
impl<T> Clone for Handle<T> {
fn clone(&self) -> Self {
2017-11-14 14:55:43 +11:00
Handle(self.0)
2017-09-07 11:34:41 +10:00
}
}
impl<T> Copy for Handle<T> {}
impl<T> ops::Deref for Handle<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.0 }
2017-09-07 11:34:41 +10:00
}
}
impl<T> ops::DerefMut for Handle<T> {
fn deref_mut(&mut self) -> &mut T {
2017-11-14 14:55:43 +11:00
unsafe { &mut *self.0 }
2017-09-07 11:34:41 +10:00
}
}
2018-02-17 02:31:10 +11:00
impl<T> borrow::Borrow<T> for Handle<T> {
fn borrow(&self) -> &T {
unsafe { &*self.0 }
}
}
impl<T> cmp::PartialEq for Handle<T> {
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}
2017-09-07 11:34:41 +10:00
impl<T> fmt::Debug for Handle<T> {
2017-11-14 14:55:43 +11:00
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "Handle({:p})", self.0)
2017-09-07 11:34:41 +10:00
}
}
2018-03-02 14:04:47 +11:00
#[cfg(feature = "dispatch")]
pub use self::dispatch::DispatchHandle;
#[cfg(not(feature = "dispatch"))]
pub type DispatchHandle<T> = Handle<T>;
2018-03-02 14:04:47 +11:00
#[cfg(feature = "dispatch")]
mod dispatch {
2018-03-15 08:24:26 +11:00
use VK_NULL_HANDLE;
use std::{borrow, cmp, fmt, ops};
2018-03-15 08:24:26 +11:00
const ICD_LOADER_MAGIC: u64 = 0x01CDC0DE;
2018-03-02 14:04:47 +11:00
#[repr(C)]
2018-03-15 08:24:26 +11:00
pub struct DispatchHandle<T>(*mut (u64, T));
2018-03-02 14:04:47 +11:00
impl<T> DispatchHandle<T> {
pub fn new(value: T) -> Self {
2018-03-15 08:24:26 +11:00
let ptr = Box::into_raw(Box::new((ICD_LOADER_MAGIC, value)));
DispatchHandle(ptr)
2018-03-02 14:04:47 +11:00
}
pub fn null() -> Self {
DispatchHandle(VK_NULL_HANDLE as *mut _)
}
2018-04-19 09:11:32 +10:00
pub fn unbox(self) -> Option<T> {
if self.0 == VK_NULL_HANDLE as *mut (u64, T) {
None
} else {
Some(unsafe { Box::from_raw(self.0) }.1)
}
2018-03-02 14:04:47 +11:00
}
2018-04-19 09:11:32 +10:00
pub fn as_ref(&self) -> Option<&T> {
if self.0 == VK_NULL_HANDLE as *mut (u64, T) {
None
} else {
Some(unsafe { &(*self.0).1 })
}
2018-03-02 14:04:47 +11:00
}
}
2018-03-02 14:04:47 +11:00
impl<T> Clone for DispatchHandle<T> {
fn clone(&self) -> Self {
2018-03-15 08:24:26 +11:00
DispatchHandle(self.0)
2018-03-02 14:04:47 +11:00
}
}
2018-03-02 14:04:47 +11:00
impl<T> Copy for DispatchHandle<T> {}
2018-03-02 14:04:47 +11:00
impl<T> ops::Deref for DispatchHandle<T> {
type Target = T;
fn deref(&self) -> &T {
2018-03-15 08:24:26 +11:00
unsafe { &(*self.0).1 }
2018-03-02 14:04:47 +11:00
}
}
2018-03-02 14:04:47 +11:00
impl<T> ops::DerefMut for DispatchHandle<T> {
fn deref_mut(&mut self) -> &mut T {
2018-03-15 08:24:26 +11:00
unsafe { &mut (*self.0).1 }
2018-03-02 14:04:47 +11:00
}
}
2018-03-02 14:04:47 +11:00
impl<T> borrow::Borrow<T> for DispatchHandle<T> {
fn borrow(&self) -> &T {
2018-03-15 08:24:26 +11:00
unsafe { &(*self.0).1 }
2018-03-02 14:04:47 +11:00
}
}
impl<T> cmp::PartialEq for DispatchHandle<T> {
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}
2018-03-02 14:04:47 +11:00
impl<T> fmt::Debug for DispatchHandle<T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2018-03-15 08:24:26 +11:00
write!(formatter, "DispatchHandle({:p})", self.0)
2018-03-02 14:04:47 +11:00
}
}
}