use super::Instance;
use std::alloc::Layout;
use std::convert::TryFrom;
use std::ptr::{self, NonNull};
use std::sync::{Arc, Weak};
#[derive(Debug)]
#[repr(C)]
struct InstanceInner {
instance_layout: Layout,
instance: NonNull<Instance>,
}
impl InstanceInner {
unsafe fn deallocate_instance(&mut self) {
let instance_ptr = self.instance.as_ptr();
ptr::drop_in_place(instance_ptr);
std::alloc::dealloc(instance_ptr as *mut u8, self.instance_layout);
}
#[inline]
pub(crate) fn as_ref(&self) -> &Instance {
unsafe { self.instance.as_ref() }
}
#[inline]
pub(super) fn as_mut(&mut self) -> &mut Instance {
unsafe { self.instance.as_mut() }
}
}
impl PartialEq for InstanceInner {
fn eq(&self, other: &Self) -> bool {
self.instance == other.instance
}
}
impl Drop for InstanceInner {
fn drop(&mut self) {
unsafe { Self::deallocate_instance(self) };
}
}
unsafe impl Send for InstanceInner {}
unsafe impl Sync for InstanceInner {}
#[derive(Debug, PartialEq, Clone)]
pub struct InstanceRef(Arc<InstanceInner>);
impl InstanceRef {
pub(super) unsafe fn new(instance: NonNull<Instance>, instance_layout: Layout) -> Self {
Self(Arc::new(InstanceInner { instance_layout, instance }))
}
#[inline]
pub fn as_ref(&self) -> &Instance {
(&*self.0).as_ref()
}
#[inline]
pub(super) fn as_mut(&mut self) -> Option<&mut Instance> {
Some(Arc::get_mut(&mut self.0)?.as_mut())
}
#[inline]
pub(super) unsafe fn as_mut_unchecked(&mut self) -> &mut Instance {
let ptr: *mut InstanceInner = Arc::as_ptr(&self.0) as *mut _;
(&mut *ptr).as_mut()
}
}
#[derive(Debug, Clone)]
pub struct WeakInstanceRef(Weak<InstanceInner>);
impl PartialEq for WeakInstanceRef {
fn eq(&self, other: &Self) -> bool {
self.0.ptr_eq(&other.0)
}
}
impl WeakInstanceRef {
pub fn upgrade(&self) -> Option<InstanceRef> {
let inner = self.0.upgrade()?;
Some(InstanceRef(inner))
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum WeakOrStrongInstanceRef {
Weak(WeakInstanceRef),
Strong(InstanceRef),
}
impl WeakOrStrongInstanceRef {
pub fn upgrade(&self) -> Option<Self> {
match self {
Self::Weak(weak) => weak.upgrade().map(Self::Strong),
Self::Strong(strong) => Some(Self::Strong(strong.clone())),
}
}
pub fn downgrade(&self) -> Self {
match self {
Self::Weak(weak) => Self::Weak(weak.clone()),
Self::Strong(strong) => Self::Weak(WeakInstanceRef(Arc::downgrade(&strong.0))),
}
}
}
impl TryFrom<WeakOrStrongInstanceRef> for InstanceRef {
type Error = &'static str;
fn try_from(value: WeakOrStrongInstanceRef) -> Result<Self, Self::Error> {
match value {
WeakOrStrongInstanceRef::Strong(strong) => Ok(strong),
WeakOrStrongInstanceRef::Weak(weak) => {
weak.upgrade().ok_or("Failed to upgrade weak reference")
}
}
}
}
impl From<WeakOrStrongInstanceRef> for WeakInstanceRef {
fn from(value: WeakOrStrongInstanceRef) -> Self {
match value {
WeakOrStrongInstanceRef::Strong(strong) => Self(Arc::downgrade(&strong.0)),
WeakOrStrongInstanceRef::Weak(weak) => weak,
}
}
}
impl From<WeakInstanceRef> for WeakOrStrongInstanceRef {
fn from(value: WeakInstanceRef) -> Self {
Self::Weak(value)
}
}
impl From<InstanceRef> for WeakOrStrongInstanceRef {
fn from(value: InstanceRef) -> Self {
Self::Strong(value)
}
}