-
-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
081b73d
commit 446f422
Showing
12 changed files
with
329 additions
and
208 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,118 +1,59 @@ | ||
use crate::{GCRuntime, Type}; | ||
use std::marker::PhantomData; | ||
use std::ptr::NonNull; | ||
use std::sync::{Arc, Weak}; | ||
|
||
/// A `GCHandle` is what you interact with outside of the allocator. It is a pointer to a piece of | ||
/// A `GCPtr` is what you interact with outside of the allocator. It is a pointer to a piece of | ||
/// memory that points to the actual data stored in memory. | ||
/// | ||
/// This creates an indirection that must be followed to get to the actual data of the object. Note | ||
/// that the indirection pointer must therefor be pinned in memory whereas the pointer stored | ||
/// at the indirection may change. | ||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] | ||
#[repr(transparent)] | ||
pub struct GCHandle(RawGCHandle); | ||
pub struct GCPtr(RawGCPtr); | ||
|
||
/// A `GCHandle` is thread safe. | ||
unsafe impl Send for GCHandle {} | ||
unsafe impl Sync for GCHandle {} | ||
/// A `GCPtr` is thread safe. | ||
unsafe impl Send for GCPtr {} | ||
unsafe impl Sync for GCPtr {} | ||
|
||
/// A `RawGCHandle` is an unsafe version of a `GCHandle`. It represents the raw internal pointer | ||
/// A `RawGCPtr` is an unsafe version of a `GCPtr`. It represents the raw internal pointer | ||
/// semantics used by the runtime. | ||
pub type RawGCHandle = *const *mut std::ffi::c_void; | ||
pub type RawGCPtr = *const *mut std::ffi::c_void; | ||
|
||
pub trait HasGCHandlePtr { | ||
pub trait HasIndirectionPtr { | ||
/// Returns a pointer to the referenced memory. | ||
/// | ||
/// # Safety | ||
/// | ||
/// This method is unsafe because casting to a generic type T may be unsafe. We don't know the | ||
/// type of the stored data. | ||
unsafe fn get_ptr<T: Sized>(&self) -> NonNull<T>; | ||
} | ||
|
||
impl HasGCHandlePtr for GCHandle { | ||
unsafe fn get_ptr<T: Sized>(&self) -> NonNull<T> { | ||
NonNull::new(*self.0) | ||
.expect("indirection pointer is null") | ||
.cast::<T>() | ||
} | ||
} | ||
|
||
impl Into<RawGCHandle> for GCHandle { | ||
fn into(self) -> RawGCHandle { | ||
self.0 | ||
} | ||
} | ||
|
||
impl Into<GCHandle> for RawGCHandle { | ||
fn into(self) -> GCHandle { | ||
GCHandle(self) | ||
} | ||
} | ||
|
||
/// A `GCHandle` that automatically roots and unroots its internal `GCHandle`. | ||
pub struct GCRootHandle<T: Type, G: GCRuntime<T>> { | ||
handle: GCHandle, | ||
runtime: Weak<G>, | ||
ty: PhantomData<T>, | ||
} | ||
|
||
impl<T: Type, G: GCRuntime<T>> Clone for GCRootHandle<T, G> { | ||
fn clone(&self) -> Self { | ||
if let Some(runtime) = self.runtime.upgrade() { | ||
unsafe { runtime.root(self.handle) } | ||
} | ||
Self { | ||
handle: self.handle, | ||
runtime: self.runtime.clone(), | ||
ty: Default::default(), | ||
} | ||
} | ||
} | ||
/// This is an unsafe method because derefencing could result in an access violation. | ||
unsafe fn deref<T: Sized>(&self) -> *const T; | ||
|
||
impl<T: Type, G: GCRuntime<T>> GCRootHandle<T, G> { | ||
/// Constructs a new GCRootHandle from a runtime and a handle | ||
/// Returns a mutable pointer to the referenced memory. | ||
/// | ||
/// # Safety | ||
/// | ||
/// This method is unsafe because the passed GCHandle could point to random memory. | ||
pub unsafe fn new(runtime: &Arc<G>, handle: GCHandle) -> Self { | ||
runtime.root(handle); | ||
Self { | ||
handle, | ||
runtime: Arc::downgrade(runtime), | ||
ty: Default::default(), | ||
} | ||
} | ||
|
||
/// Returns the handle of this instance | ||
pub fn handle(&self) -> GCHandle { | ||
self.handle | ||
/// This is an unsafe method because derefencing could result in an access violation. | ||
unsafe fn deref_mut<T: Sized>(&self) -> *mut T { | ||
self.deref::<T>() as *mut _ | ||
} | ||
} | ||
|
||
/// Unroots the handle consuming self and returning the unrooted handle | ||
pub fn unroot(self) -> GCHandle { | ||
self.handle | ||
impl HasIndirectionPtr for GCPtr { | ||
unsafe fn deref<T: Sized>(&self) -> *const T { | ||
(*self.0).cast() | ||
} | ||
} | ||
|
||
impl<T: Type, G: GCRuntime<T>> Into<GCHandle> for GCRootHandle<T, G> { | ||
fn into(self) -> GCHandle { | ||
self.handle | ||
impl Into<RawGCPtr> for GCPtr { | ||
fn into(self) -> RawGCPtr { | ||
self.0 | ||
} | ||
} | ||
|
||
impl<T: Type, G: GCRuntime<T>> Drop for GCRootHandle<T, G> { | ||
fn drop(&mut self) { | ||
if let Some(runtime) = self.runtime.upgrade() { | ||
unsafe { runtime.unroot(self.handle) } | ||
} | ||
impl Into<GCPtr> for RawGCPtr { | ||
fn into(self) -> GCPtr { | ||
GCPtr(self) | ||
} | ||
} | ||
|
||
impl<T: Type, G: GCRuntime<T>> HasGCHandlePtr for GCRootHandle<T, G> { | ||
unsafe fn get_ptr<R: Sized>(&self) -> NonNull<R> { | ||
self.handle.get_ptr() | ||
impl GCPtr { | ||
pub(crate) fn as_ptr(self) -> RawGCPtr { | ||
self.0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.