cycle_ptr 0.1.1

Smart pointers, with cycles
Documentation
//! Implement the various object pointers.
//!
//! These are all reference-counted pointers.
//! The reason we don't use [Rc][std::rc::Rc] or [Arc][std::sync::Arc],
//! is because the garbage controller needs to increment and decrement
//! the reference counter to these objects during its work.
//! [Rc][std::rc::Rc] and [Arc][std::sync::Arc] won't permit this in a type-erased fashion.
//!
//! We don't have a need of weak pointers either,
//! so the implementation is a little simpler than for
//! [Rc][std::rc::Rc]/[Arc][std::sync::Arc].
#[cfg(feature = "multi_thread")]
use super::MTObject;
#[cfg(feature = "multi_thread")]
use super::MTObjectIntf;
use super::{Object, ObjectIntf};
use crate::util::NonNull;
use std::mem;
use std::ops::Deref;
use std::pin::Pin;

/// Reference-counted pointer to [Object].
pub(crate) struct ObjectPtr<T>
where
    T: 'static,
{
    /// Pointer to the [Object] holding on to `T` and its associated [ControlBlock][crate::generation::ControlBlock].
    ptr: NonNull<Object<T>>,
}

/// Reference-counted pointer to [MTObject].
#[cfg(feature = "multi_thread")]
pub(crate) struct MTObjectPtr<T>
where
    T: 'static,
{
    /// Pointer to the [Object] holding on to an [MTObject] and its associated [MTControlBlock][crate::generation::MTControlBlock].
    ptr: NonNull<MTObject<T>>,
}

/// Reference-counted type-erased pointer to [ObjectIntf].
pub(crate) struct DynObjectPtr {
    /// Pointer to the [Object] holding on to an arbitrary object and its associated [ControlBlock][crate::generation::ControlBlock].
    ptr: NonNull<dyn ObjectIntf>,
}

/// Reference-counted type-erased pointer to [MTObjectIntf].
#[cfg(feature = "multi_thread")]
pub(crate) struct DynMTObjectPtr {
    /// Pointer to the [MTObject] holding on to an arbitrary object and its associated [MTControlBlock][crate::generation::MTControlBlock].
    ptr: NonNull<dyn Send + Sync + MTObjectIntf>,
}

#[cfg(feature = "multi_thread")]
unsafe impl<T> Send for MTObjectPtr<T>
where
    MTObject<T>: Send + Sync,
    T: 'static,
{
}
#[cfg(feature = "multi_thread")]
unsafe impl<T> Sync for MTObjectPtr<T>
where
    MTObject<T>: Send + Sync,
    T: 'static,
{
}

#[cfg(feature = "multi_thread")]
unsafe impl Send for DynMTObjectPtr {}
#[cfg(feature = "multi_thread")]
unsafe impl Sync for DynMTObjectPtr {}

impl<T> From<ObjectPtr<T>> for DynObjectPtr
where
    T: 'static,
{
    /// Create a type-erased pointer from a typed pointer.
    #[inline]
    fn from(obj_ptr: ObjectPtr<T>) -> Self {
        let obj_ptr = mem::ManuallyDrop::new(obj_ptr);
        DynObjectPtr {
            ptr: NonNull::from_ptr(obj_ptr.ptr.as_ptr()),
        }
    }
}

#[cfg(feature = "multi_thread")]
impl<T> From<MTObjectPtr<T>> for DynMTObjectPtr
where
    T: 'static + Send + Sync,
{
    /// Create a type-erased pointer from a typed pointer.
    #[inline]
    fn from(obj_ptr: MTObjectPtr<T>) -> Self {
        let obj_ptr = mem::ManuallyDrop::new(obj_ptr);
        DynMTObjectPtr {
            ptr: NonNull::from_ptr(obj_ptr.ptr.as_ptr()),
        }
    }
}

impl<T> From<Pin<ObjectPtr<T>>> for Pin<DynObjectPtr>
where
    T: 'static,
{
    /// Create a type-erased pointer from a typed pointer, maintaining the [Pin].
    #[inline]
    fn from(obj_ptr: Pin<ObjectPtr<T>>) -> Self {
        unsafe { Pin::new_unchecked(DynObjectPtr::from(Pin::into_inner_unchecked(obj_ptr))) }
    }
}

#[cfg(feature = "multi_thread")]
impl<T> From<Pin<MTObjectPtr<T>>> for Pin<DynMTObjectPtr>
where
    T: 'static + Send + Sync,
{
    /// Create a type-erased pointer from a typed pointer, maintaining the [Pin].
    #[inline]
    fn from(obj_ptr: Pin<MTObjectPtr<T>>) -> Self {
        unsafe { Pin::new_unchecked(DynMTObjectPtr::from(Pin::into_inner_unchecked(obj_ptr))) }
    }
}

impl<T> Drop for ObjectPtr<T>
where
    T: 'static,
{
    fn drop(&mut self) {
        unsafe {
            self.ptr.as_ref().refcount_dec(); // May invalidate `self.ptr`.
        }
    }
}

#[cfg(feature = "multi_thread")]
impl<T> Drop for MTObjectPtr<T>
where
    T: 'static,
{
    fn drop(&mut self) {
        unsafe {
            self.ptr.as_ref().refcount_dec(); // May invalidate `self.ptr`.
        }
    }
}

impl Drop for DynObjectPtr {
    fn drop(&mut self) {
        unsafe {
            self.ptr.as_ref().refcount_dec(); // May invalidate `self.ptr`.
        }
    }
}

#[cfg(feature = "multi_thread")]
impl Drop for DynMTObjectPtr {
    fn drop(&mut self) {
        unsafe {
            self.ptr.as_ref().refcount_dec(); // May invalidate `self.ptr`.
        }
    }
}

impl<T> Deref for ObjectPtr<T>
where
    T: 'static,
{
    type Target = Object<T>;

    fn deref(&self) -> &Self::Target {
        unsafe { self.ptr.as_ref() }
    }
}

#[cfg(feature = "multi_thread")]
impl<T> Deref for MTObjectPtr<T>
where
    T: 'static,
{
    type Target = MTObject<T>;

    fn deref(&self) -> &Self::Target {
        unsafe { self.ptr.as_ref() }
    }
}

impl Deref for DynObjectPtr {
    type Target = dyn ObjectIntf;

    fn deref(&self) -> &Self::Target {
        unsafe { self.ptr.as_ref() }
    }
}

#[cfg(feature = "multi_thread")]
impl Deref for DynMTObjectPtr {
    type Target = dyn Send + Sync + MTObjectIntf;

    fn deref(&self) -> &Self::Target {
        unsafe { self.ptr.as_ref() }
    }
}

impl<T> Clone for ObjectPtr<T>
where
    T: 'static,
{
    fn clone(&self) -> Self {
        unsafe { self.ptr.as_ref().refcount_inc() };
        ObjectPtr {
            ptr: self.ptr.clone(),
        }
    }
}

#[cfg(feature = "multi_thread")]
impl<T> Clone for MTObjectPtr<T>
where
    T: 'static,
{
    fn clone(&self) -> Self {
        unsafe { self.ptr.as_ref().refcount_inc() };
        MTObjectPtr {
            ptr: self.ptr.clone(),
        }
    }
}

impl Clone for DynObjectPtr {
    fn clone(&self) -> Self {
        unsafe { self.ptr.as_ref().refcount_inc() };
        DynObjectPtr {
            ptr: self.ptr.clone(),
        }
    }
}

#[cfg(feature = "multi_thread")]
impl Clone for DynMTObjectPtr {
    fn clone(&self) -> Self {
        unsafe { self.ptr.as_ref().refcount_inc() };
        DynMTObjectPtr {
            ptr: self.ptr.clone(),
        }
    }
}

impl<T> ObjectPtr<T>
where
    T: 'static,
{
    /// Create a pointer from a pinned [Object] reference.
    ///
    /// This function will increment the reference counter.
    pub(super) fn new(obj_ref: Pin<&Object<T>>) -> Pin<Self> {
        obj_ref.refcount_inc();
        unsafe {
            Pin::new_unchecked(ObjectPtr {
                ptr: NonNull::from_ref(obj_ref.get_ref()),
            })
        }
    }
}

#[cfg(feature = "multi_thread")]
impl<T> MTObjectPtr<T>
where
    T: 'static + Send + Sync,
{
    /// Create a pointer from a pinned [MTObject] reference.
    ///
    /// This function will increment the reference counter.
    pub(super) fn new(obj_ref: Pin<&MTObject<T>>) -> Pin<Self> {
        obj_ref.refcount_inc();
        unsafe {
            Pin::new_unchecked(MTObjectPtr {
                ptr: NonNull::from_ref(obj_ref.get_ref()),
            })
        }
    }
}