Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use associated type in memory managers #1171

Merged
merged 2 commits into from
Aug 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 28 additions & 24 deletions glib/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,15 +420,17 @@ macro_rules! glib_boxed_wrapper {

(@memory_manager_impl $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $ffi_name:ty, @copy $copy_arg:ident $copy_expr:expr, @free $free_arg:ident $free_expr:expr) => {
#[doc(hidden)]
impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::boxed::BoxedMemoryManager<$ffi_name> for $name $(<$($generic),+>)? {
impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::boxed::BoxedMemoryManager for $name $(<$($generic),+>)? {
type Target = $ffi_name;

#[inline]
unsafe fn copy($copy_arg: *const $ffi_name) -> *mut $ffi_name {
unsafe fn copy($copy_arg: *const Self::Target) -> *mut Self::Target {
$copy_expr
}

#[inline]
#[allow(clippy::no_effect)]
unsafe fn free($free_arg: *mut $ffi_name) {
unsafe fn free($free_arg: *mut Self::Target) {
$free_expr;
}
}
Expand All @@ -437,21 +439,23 @@ macro_rules! glib_boxed_wrapper {

// The safety docs really belong in the wrapper!() macro for Boxed<T>
/// Memory management functions for a boxed type.
pub trait BoxedMemoryManager<T>: 'static {
pub trait BoxedMemoryManager: 'static {
type Target;

/// Makes a copy.
unsafe fn copy(ptr: *const T) -> *mut T;
unsafe fn copy(ptr: *const Self::Target) -> *mut Self::Target;
/// Frees the object.
unsafe fn free(ptr: *mut T);
unsafe fn free(ptr: *mut Self::Target);
}

/// Encapsulates memory management logic for boxed types.
#[repr(transparent)]
pub struct Boxed<T: 'static, MM: BoxedMemoryManager<T>> {
pub struct Boxed<T: 'static, MM: BoxedMemoryManager<Target = T>> {
inner: ptr::NonNull<T>,
_dummy: PhantomData<*mut MM>,
}

impl<'a, T: 'static, MM: BoxedMemoryManager<T>> ToGlibPtr<'a, *const T> for Boxed<T, MM> {
impl<'a, T: 'static, MM: BoxedMemoryManager<Target = T>> ToGlibPtr<'a, *const T> for Boxed<T, MM> {
type Storage = PhantomData<&'a Self>;

#[inline]
Expand All @@ -467,7 +471,7 @@ impl<'a, T: 'static, MM: BoxedMemoryManager<T>> ToGlibPtr<'a, *const T> for Boxe
}
}

impl<'a, T: 'static, MM: BoxedMemoryManager<T>> ToGlibPtrMut<'a, *mut T> for Boxed<T, MM> {
impl<'a, T: 'static, MM: BoxedMemoryManager<Target = T>> ToGlibPtrMut<'a, *mut T> for Boxed<T, MM> {
type Storage = PhantomData<&'a mut Self>;

#[inline]
Expand All @@ -477,7 +481,7 @@ impl<'a, T: 'static, MM: BoxedMemoryManager<T>> ToGlibPtrMut<'a, *mut T> for Box
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrNone<*mut T> for Boxed<T, MM> {
impl<T: 'static, MM: BoxedMemoryManager<Target = T>> FromGlibPtrNone<*mut T> for Boxed<T, MM> {
#[inline]
unsafe fn from_glib_none(ptr: *mut T) -> Self {
debug_assert!(!ptr.is_null());
Expand All @@ -486,7 +490,7 @@ impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrNone<*mut T> for Boxed<T,
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrNone<*const T> for Boxed<T, MM> {
impl<T: 'static, MM: BoxedMemoryManager<Target = T>> FromGlibPtrNone<*const T> for Boxed<T, MM> {
#[inline]
unsafe fn from_glib_none(ptr: *const T) -> Self {
debug_assert!(!ptr.is_null());
Expand All @@ -495,7 +499,7 @@ impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrNone<*const T> for Boxed<
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrFull<*mut T> for Boxed<T, MM> {
impl<T: 'static, MM: BoxedMemoryManager<Target = T>> FromGlibPtrFull<*mut T> for Boxed<T, MM> {
#[inline]
unsafe fn from_glib_full(ptr: *mut T) -> Self {
debug_assert!(!ptr.is_null());
Expand All @@ -506,7 +510,7 @@ impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrFull<*mut T> for Boxed<T,
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrFull<*const T> for Boxed<T, MM> {
impl<T: 'static, MM: BoxedMemoryManager<Target = T>> FromGlibPtrFull<*const T> for Boxed<T, MM> {
#[inline]
unsafe fn from_glib_full(ptr: *const T) -> Self {
debug_assert!(!ptr.is_null());
Expand All @@ -517,7 +521,7 @@ impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrFull<*const T> for Boxed<
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrBorrow<*mut T> for Boxed<T, MM> {
impl<T: 'static, MM: BoxedMemoryManager<Target = T>> FromGlibPtrBorrow<*mut T> for Boxed<T, MM> {
#[inline]
unsafe fn from_glib_borrow(ptr: *mut T) -> Borrowed<Self> {
debug_assert!(!ptr.is_null());
Expand All @@ -528,7 +532,7 @@ impl<T: 'static, MM: BoxedMemoryManager<T>> FromGlibPtrBorrow<*mut T> for Boxed<
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> Drop for Boxed<T, MM> {
impl<T: 'static, MM: BoxedMemoryManager<Target = T>> Drop for Boxed<T, MM> {
#[inline]
fn drop(&mut self) {
unsafe {
Expand All @@ -537,36 +541,36 @@ impl<T: 'static, MM: BoxedMemoryManager<T>> Drop for Boxed<T, MM> {
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> fmt::Debug for Boxed<T, MM> {
impl<T: 'static, MM: BoxedMemoryManager<Target = T>> fmt::Debug for Boxed<T, MM> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Boxed").field("inner", &self.inner).finish()
}
}

impl<T, MM: BoxedMemoryManager<T>> PartialOrd for Boxed<T, MM> {
impl<T, MM: BoxedMemoryManager<Target = T>> PartialOrd for Boxed<T, MM> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.to_glib_none().0.partial_cmp(&other.to_glib_none().0)
}
}

impl<T, MM: BoxedMemoryManager<T>> Ord for Boxed<T, MM> {
impl<T, MM: BoxedMemoryManager<Target = T>> Ord for Boxed<T, MM> {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.to_glib_none().0.cmp(&other.to_glib_none().0)
}
}

impl<T, MM: BoxedMemoryManager<T>> PartialEq for Boxed<T, MM> {
impl<T, MM: BoxedMemoryManager<Target = T>> PartialEq for Boxed<T, MM> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.to_glib_none().0 == other.to_glib_none().0
}
}

impl<T, MM: BoxedMemoryManager<T>> Eq for Boxed<T, MM> {}
impl<T, MM: BoxedMemoryManager<Target = T>> Eq for Boxed<T, MM> {}

impl<T, MM: BoxedMemoryManager<T>> Hash for Boxed<T, MM> {
impl<T, MM: BoxedMemoryManager<Target = T>> Hash for Boxed<T, MM> {
#[inline]
fn hash<H>(&self, state: &mut H)
where
Expand All @@ -576,14 +580,14 @@ impl<T, MM: BoxedMemoryManager<T>> Hash for Boxed<T, MM> {
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> Clone for Boxed<T, MM> {
impl<T: 'static, MM: BoxedMemoryManager<Target = T>> Clone for Boxed<T, MM> {
#[inline]
fn clone(&self) -> Self {
unsafe { from_glib_none(self.to_glib_none().0 as *mut T) }
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> Deref for Boxed<T, MM> {
impl<T: 'static, MM: BoxedMemoryManager<Target = T>> Deref for Boxed<T, MM> {
type Target = T;

#[inline]
Expand All @@ -595,7 +599,7 @@ impl<T: 'static, MM: BoxedMemoryManager<T>> Deref for Boxed<T, MM> {
}
}

impl<T: 'static, MM: BoxedMemoryManager<T>> DerefMut for Boxed<T, MM> {
impl<T: 'static, MM: BoxedMemoryManager<Target = T>> DerefMut for Boxed<T, MM> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe {
Expand Down
44 changes: 24 additions & 20 deletions glib/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,17 @@ macro_rules! glib_shared_wrapper {
}

#[doc(hidden)]
impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::shared::SharedMemoryManager<$ffi_name> for $name $(<$($generic),+>)? {
impl $(<$($generic $(: $bound $(+ $bound2)*)?),+>)? $crate::shared::SharedMemoryManager for $name $(<$($generic),+>)? {
type Target = $ffi_name;

#[inline]
unsafe fn ref_($ref_arg: *mut $ffi_name) {
unsafe fn ref_($ref_arg: *mut Self::Target) {
$ref_expr;
}

#[inline]
#[allow(clippy::no_effect)]
unsafe fn unref($unref_arg: *mut $ffi_name) {
unsafe fn unref($unref_arg: *mut Self::Target) {
$unref_expr;
}
}
Expand Down Expand Up @@ -436,29 +438,31 @@ macro_rules! glib_shared_wrapper {
};
}

pub trait SharedMemoryManager<T> {
pub trait SharedMemoryManager {
type Target;

/// # Safety
///
/// Callers are responsible for ensuring that a matching call to `unref`
/// is made at an appropriate time.
unsafe fn ref_(ptr: *mut T);
unsafe fn ref_(ptr: *mut Self::Target);

/// # Safety
///
/// Callers are responsible for ensuring that a matching call to `ref` was
/// made before this is called, and that the pointer is not used after the
/// `unref` call.
unsafe fn unref(ptr: *mut T);
unsafe fn unref(ptr: *mut Self::Target);
}

/// Encapsulates memory management logic for shared types.
#[repr(transparent)]
pub struct Shared<T, MM: SharedMemoryManager<T>> {
pub struct Shared<T, MM: SharedMemoryManager<Target = T>> {
inner: ptr::NonNull<T>,
mm: PhantomData<*const MM>,
}

impl<T, MM: SharedMemoryManager<T>> Drop for Shared<T, MM> {
impl<T, MM: SharedMemoryManager<Target = T>> Drop for Shared<T, MM> {
#[inline]
fn drop(&mut self) {
unsafe {
Expand All @@ -467,7 +471,7 @@ impl<T, MM: SharedMemoryManager<T>> Drop for Shared<T, MM> {
}
}

impl<T, MM: SharedMemoryManager<T>> Clone for Shared<T, MM> {
impl<T, MM: SharedMemoryManager<Target = T>> Clone for Shared<T, MM> {
#[inline]
fn clone(&self) -> Self {
unsafe {
Expand All @@ -480,38 +484,38 @@ impl<T, MM: SharedMemoryManager<T>> Clone for Shared<T, MM> {
}
}

impl<T, MM: SharedMemoryManager<T>> fmt::Debug for Shared<T, MM> {
impl<T, MM: SharedMemoryManager<Target = T>> fmt::Debug for Shared<T, MM> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Shared")
.field("inner", &self.inner)
.finish()
}
}

impl<T, MM: SharedMemoryManager<T>> PartialOrd for Shared<T, MM> {
impl<T, MM: SharedMemoryManager<Target = T>> PartialOrd for Shared<T, MM> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.inner.partial_cmp(&other.inner)
}
}

impl<T, MM: SharedMemoryManager<T>> Ord for Shared<T, MM> {
impl<T, MM: SharedMemoryManager<Target = T>> Ord for Shared<T, MM> {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.inner.cmp(&other.inner)
}
}

impl<T, MM: SharedMemoryManager<T>> PartialEq for Shared<T, MM> {
impl<T, MM: SharedMemoryManager<Target = T>> PartialEq for Shared<T, MM> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}

impl<T, MM: SharedMemoryManager<T>> Eq for Shared<T, MM> {}
impl<T, MM: SharedMemoryManager<Target = T>> Eq for Shared<T, MM> {}

impl<T, MM: SharedMemoryManager<T>> Hash for Shared<T, MM> {
impl<T, MM: SharedMemoryManager<Target = T>> Hash for Shared<T, MM> {
#[inline]
fn hash<H>(&self, state: &mut H)
where
Expand All @@ -523,7 +527,7 @@ impl<T, MM: SharedMemoryManager<T>> Hash for Shared<T, MM> {

impl<'a, T: 'static, MM> ToGlibPtr<'a, *mut T> for Shared<T, MM>
where
MM: SharedMemoryManager<T> + 'static,
MM: SharedMemoryManager<Target = T> + 'static,
{
type Storage = PhantomData<&'a Self>;

Expand All @@ -541,7 +545,7 @@ where
}
}

impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrNone<*mut T> for Shared<T, MM> {
impl<T: 'static, MM: SharedMemoryManager<Target = T>> FromGlibPtrNone<*mut T> for Shared<T, MM> {
#[inline]
unsafe fn from_glib_none(ptr: *mut T) -> Self {
debug_assert!(!ptr.is_null());
Expand All @@ -553,7 +557,7 @@ impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrNone<*mut T> for Shared<
}
}

impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrNone<*const T> for Shared<T, MM> {
impl<T: 'static, MM: SharedMemoryManager<Target = T>> FromGlibPtrNone<*const T> for Shared<T, MM> {
#[inline]
unsafe fn from_glib_none(ptr: *const T) -> Self {
debug_assert!(!ptr.is_null());
Expand All @@ -565,7 +569,7 @@ impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrNone<*const T> for Share
}
}

impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrFull<*mut T> for Shared<T, MM> {
impl<T: 'static, MM: SharedMemoryManager<Target = T>> FromGlibPtrFull<*mut T> for Shared<T, MM> {
#[inline]
unsafe fn from_glib_full(ptr: *mut T) -> Self {
debug_assert!(!ptr.is_null());
Expand All @@ -576,7 +580,7 @@ impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrFull<*mut T> for Shared<
}
}

impl<T: 'static, MM: SharedMemoryManager<T>> FromGlibPtrBorrow<*mut T> for Shared<T, MM> {
impl<T: 'static, MM: SharedMemoryManager<Target = T>> FromGlibPtrBorrow<*mut T> for Shared<T, MM> {
#[inline]
unsafe fn from_glib_borrow(ptr: *mut T) -> Borrowed<Self> {
debug_assert!(!ptr.is_null());
Expand Down
Loading