From 6e7765623399dcfe681bfcb72a2f0c073bbb2ace Mon Sep 17 00:00:00 2001 From: Tin Svagelj Date: Mon, 28 Aug 2023 08:52:03 +0200 Subject: [PATCH] Add support for ptr_metadata Signed-off-by: Tin Svagelj --- Cargo.toml | 5 ++-- src/lib.rs | 78 +++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b0e4796..c11fdfc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "contiguous-mem" -version = "0.1.0" +version = "0.1.1" edition = "2021" description = "A contiguous memory storage" authors = ["Tin Å vagelj "] @@ -20,7 +20,8 @@ portable-atomic = { version = "1", default-features = false } spin = { version = "0.9", optional = true } [features] -default = ["std"] +default = ["std", "ptr_metadata"] std = ["portable-atomic/std"] no_std = ["dep:spin"] debug = [] +ptr_metadata = [] diff --git a/src/lib.rs b/src/lib.rs index 2e8d1ed..bdd4f86 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(feature = "no_std", no_std)] +#![cfg_attr(feature = "ptr_metadata", feature(ptr_metadata))] #[cfg(feature = "no_std")] extern crate alloc; @@ -15,11 +16,13 @@ pub mod error; use core::{ cell::{Cell, RefCell}, - marker::PhantomData, mem::size_of, - ptr::{null_mut, write_unaligned}, + ptr::{null_mut, write_unaligned, Pointee}, }; +#[cfg(not(feature = "ptr_metadata"))] +use core::marker::PhantomData; + #[cfg(feature = "std")] mod std_imports { pub use std::alloc::{Layout, LayoutError}; @@ -464,7 +467,7 @@ pub trait ImplDetails { type AllocationTracker: Clone; /// The type representing the result of an allocation operation. - type AllocResult; + type AllocResult; /// The type representing the usage counter in [`crate::Ref`] type. type UseCounter: Clone; @@ -534,7 +537,7 @@ pub struct ThreadSafeImpl; impl ImplDetails for ThreadSafeImpl { type Base = Arc>; type AllocationTracker = Arc>; - type AllocResult = Ref; + type AllocResult = CMRef; type UseCounter = Arc; const USE_LOCKS: bool = true; @@ -622,11 +625,14 @@ impl ImplDetails for ThreadSafeImpl { range: &ByteRange, tracker: &Self::AllocationTracker, ) -> Self::AllocResult { - Ref { + CMRef { base: base.clone(), range: range.clone(), tracker: tracker.clone(), uses: Arc::new(AtomicUsize::new(1)), + #[cfg(feature = "ptr_metadata")] + metadata: (), + #[cfg(not(feature = "ptr_metadata"))] _phantom: PhantomData, } } @@ -650,7 +656,7 @@ pub struct NotThreadSafeImpl; impl ImplDetails for NotThreadSafeImpl { type Base = Rc>; type AllocationTracker = Rc>; - type AllocResult = Ref; + type AllocResult = CMRef; type UseCounter = Rc>; #[inline(always)] @@ -723,11 +729,14 @@ impl ImplDetails for NotThreadSafeImpl { range: &ByteRange, tracker: &Self::AllocationTracker, ) -> Self::AllocResult { - Ref { + CMRef { base: base.clone(), range: range.clone(), tracker: tracker.clone(), uses: Rc::new(Cell::new(1)), + #[cfg(feature = "ptr_metadata")] + metadata: (), + #[cfg(not(feature = "ptr_metadata"))] _phantom: PhantomData, } } @@ -752,7 +761,7 @@ pub struct FixedSizeImpl; impl ImplDetails for FixedSizeImpl { type Base = *mut u8; type AllocationTracker = AllocationTracker; - type AllocResult = *mut T; + type AllocResult = *mut T; type UseCounter = (); const CAN_GROW: bool = false; @@ -1036,15 +1045,40 @@ impl Drop for ContiguousMemory { } /// A reference to `T` data stored in a [`ContiguousMemory`] structure. -pub struct Ref { +pub struct CMRef { base: S::Base, range: ByteRange, tracker: S::AllocationTracker, uses: S::UseCounter, + #[cfg(feature = "ptr_metadata")] + metadata: ::Metadata, + #[cfg(not(feature = "ptr_metadata"))] _phantom: PhantomData, } +/// [`CMRef`] re-export to keep API compatibility with 0.1.* +pub type Ref = CMRef; + +#[cfg(feature = "ptr_metadata")] +impl CMRef { + pub unsafe fn as_dyn( + &self, + metadata: ::Metadata, + ) -> CMRef { + CMRef { + base: self.base.clone(), + range: self.range.clone(), + tracker: self.tracker.clone(), + uses: self.uses.clone(), + #[cfg(feature = "ptr_metadata")] + metadata: core::mem::transmute(metadata), + #[cfg(not(feature = "ptr_metadata"))] + _phantom: PhantomData, + } + } +} -impl Ref { +#[cfg(not(feature = "ptr_metadata"))] +impl CMRef { /// Tries accessing referenced data at its current location. /// /// Returns a [`Poisoned`](ContiguousMemoryError::Poisoned) error if the Mutex @@ -1057,20 +1091,38 @@ impl Ref { } } -impl Clone for Ref { +#[cfg(feature = "ptr_metadata")] +impl CMRef { + /// Tries accessing referenced data at its current location. + /// + /// Returns a [`Poisoned`](ContiguousMemoryError::Poisoned) error if the Mutex + /// holding the `base` address pointer has been poisoned. + pub fn get(&self) -> Result<&T, ContiguousMemoryError> { + unsafe { + let base = S::get_base(&self.base)?.offset(self.range.0 as isize); + let fat: *const T = core::ptr::from_raw_parts::(base as *const (), self.metadata); + Ok(&*fat) + } + } +} + +impl Clone for CMRef { fn clone(&self) -> Self { S::bump_ref(&self.uses); - Ref { + CMRef { base: self.base.clone(), range: self.range.clone(), tracker: self.tracker.clone(), uses: self.uses.clone(), + #[cfg(feature = "ptr_metadata")] + metadata: self.metadata.clone(), + #[cfg(not(feature = "ptr_metadata"))] _phantom: PhantomData, } } } -impl Drop for Ref { +impl Drop for CMRef { fn drop(&mut self) { if S::drop_ref(&mut self.uses) { let _ = S::release_range(&mut self.tracker, self.range);