infinity_pool/handles/
managed_mut.rs

1use std::borrow::{Borrow, BorrowMut};
2use std::ops::{Deref, DerefMut};
3use std::pin::Pin;
4use std::ptr::NonNull;
5use std::sync::{Arc, Mutex};
6use std::{fmt, mem, ptr};
7
8use crate::{ERR_POISONED_LOCK, Pooled, RawOpaquePoolSend, RawPooledMut};
9
10// Note that while this is a thread-safe handle, we do not require `T: Send` because
11// we do not want to require every trait we cast into via trait object to be `Send`.
12// It is the responsibility of the pool to ensure that only `Send` objects are inserted.
13
14/// A unique thread-safe reference-counting handle for a pooled object.
15#[doc = include_str!("../../doc/snippets/ref_counted_handle_implications.md")]
16#[doc = include_str!("../../doc/snippets/unique_handle_implications.md")]
17#[doc = include_str!("../../doc/snippets/nonlocal_handle_thread_safety.md")]
18pub struct PooledMut<T: ?Sized> {
19    inner: RawPooledMut<T>,
20    pool: Arc<Mutex<RawOpaquePoolSend>>,
21}
22
23impl<T: ?Sized> PooledMut<T> {
24    #[must_use]
25    pub(crate) fn new(inner: RawPooledMut<T>, pool: Arc<Mutex<RawOpaquePoolSend>>) -> Self {
26        Self { inner, pool }
27    }
28
29    #[doc = include_str!("../../doc/snippets/handle_ptr.md")]
30    #[must_use]
31    #[inline]
32    pub fn ptr(&self) -> NonNull<T> {
33        self.inner.ptr()
34    }
35
36    #[doc = include_str!("../../doc/snippets/handle_erase.md")]
37    #[must_use]
38    #[inline]
39    pub fn erase(self) -> PooledMut<()> {
40        let (inner, pool) = self.into_parts();
41
42        PooledMut {
43            inner: inner.erase(),
44            pool,
45        }
46    }
47
48    #[doc = include_str!("../../doc/snippets/handle_into_shared.md")]
49    #[must_use]
50    #[inline]
51    pub fn into_shared(self) -> Pooled<T> {
52        let (inner, pool) = self.into_parts();
53
54        Pooled::new(inner, pool)
55    }
56
57    fn into_parts(self) -> (RawPooledMut<T>, Arc<Mutex<RawOpaquePoolSend>>) {
58        // We transfer these fields to the caller, so we do not want the current handle
59        // to be dropped. Hence we perform raw reads to extract the fields directly.
60
61        // SAFETY: The target is valid for reads.
62        let pool = unsafe { ptr::read(&raw const self.pool) };
63        // SAFETY: The target is valid for reads.
64        let inner = unsafe { ptr::read(&raw const self.inner) };
65
66        // We are just "destructuring with Drop" here.
67        mem::forget(self);
68
69        (inner, pool)
70    }
71
72    #[doc = include_str!("../../doc/snippets/ref_counted_as_pin.md")]
73    #[must_use]
74    #[inline]
75    pub fn as_pin(&self) -> Pin<&T> {
76        // SAFETY: Pooled items are always pinned.
77        unsafe { Pin::new_unchecked(self) }
78    }
79
80    #[doc = include_str!("../../doc/snippets/ref_counted_as_pin_mut.md")]
81    #[must_use]
82    #[inline]
83    pub fn as_pin_mut(&mut self) -> Pin<&mut T> {
84        // SAFETY: This is a unique handle, so we guarantee borrow safety
85        // of the target object by borrowing the handle itself.
86        let as_mut = unsafe { self.ptr().as_mut() };
87
88        // SAFETY: Pooled items are always pinned.
89        unsafe { Pin::new_unchecked(as_mut) }
90    }
91
92    /// Casts this handle to reference the target as a trait object.
93    ///
94    /// This method is only intended for use by the [`define_pooled_dyn_cast!`] macro
95    /// for type-safe casting operations.
96    ///
97    /// # Safety
98    ///
99    /// The caller must guarantee that the provided closure's input and output references
100    /// point to the same object.
101    #[doc(hidden)]
102    #[must_use]
103    #[inline]
104    pub unsafe fn __private_cast_dyn_with_fn<U: ?Sized, F>(self, cast_fn: F) -> PooledMut<U>
105    where
106        F: FnOnce(&mut T) -> &mut U,
107    {
108        let (inner, pool) = self.into_parts();
109
110        // SAFETY: Forwarding callback safety guarantees from the caller.
111        // We are an exclusive handle, so we always have the right to create
112        // exclusive references to the target of the handle, satisfying that requirement.
113        let new_inner = unsafe { inner.__private_cast_dyn_with_fn(cast_fn) };
114
115        PooledMut {
116            inner: new_inner,
117            pool,
118        }
119    }
120}
121
122impl<T> PooledMut<T>
123where
124    T: Unpin,
125{
126    #[doc = include_str!("../../doc/snippets/ref_counted_into_inner.md")]
127    #[must_use]
128    #[inline]
129    pub fn into_inner(self) -> T {
130        let (inner, pool) = self.into_parts();
131
132        let mut pool = pool.lock().expect(ERR_POISONED_LOCK);
133        pool.remove_mut_unpin(inner)
134    }
135}
136
137impl<T: ?Sized> fmt::Debug for PooledMut<T> {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        f.debug_struct("PooledMut")
140            .field("inner", &self.inner)
141            .field("pool", &self.pool)
142            .finish()
143    }
144}
145
146impl<T: ?Sized> Deref for PooledMut<T> {
147    type Target = T;
148
149    #[inline]
150    fn deref(&self) -> &Self::Target {
151        // SAFETY: This is a unique handle, so we guarantee borrow safety
152        // of the target object by borrowing the handle itself.
153        // We guarantee liveness by being a reference counted handle.
154        unsafe { self.ptr().as_ref() }
155    }
156}
157
158impl<T> DerefMut for PooledMut<T>
159where
160    T: ?Sized + Unpin,
161{
162    #[inline]
163    fn deref_mut(&mut self) -> &mut Self::Target {
164        // SAFETY: This is a unique handle, so we guarantee borrow safety
165        // of the target object by borrowing the handle itself.
166        // We guarantee liveness by being a reference counted handle.
167        unsafe { self.ptr().as_mut() }
168    }
169}
170
171impl<T: ?Sized> Borrow<T> for PooledMut<T> {
172    #[inline]
173    fn borrow(&self) -> &T {
174        self
175    }
176}
177
178impl<T> BorrowMut<T> for PooledMut<T>
179where
180    T: ?Sized + Unpin,
181{
182    #[inline]
183    fn borrow_mut(&mut self) -> &mut T {
184        self
185    }
186}
187
188impl<T: ?Sized> AsRef<T> for PooledMut<T> {
189    #[inline]
190    fn as_ref(&self) -> &T {
191        self
192    }
193}
194
195impl<T> AsMut<T> for PooledMut<T>
196where
197    T: ?Sized + Unpin,
198{
199    #[inline]
200    fn as_mut(&mut self) -> &mut T {
201        self
202    }
203}
204
205impl<T: ?Sized> Drop for PooledMut<T> {
206    fn drop(&mut self) {
207        // While `RawPooledMut` is technically not Copy, we use our insider knowledge
208        // that actually it is in reality just a fat pointer, so we can actually copy it.
209        // The only reason it is not Copy is to ensure uniqueness, which we do not care
210        // about here because the copy in `self` is going away. We just do not want to
211        // insert an Option that we have to check in every method.
212        //
213        // SAFETY: The target is valid for reads.
214        let inner = unsafe { ptr::read(&raw const self.inner) };
215
216        let mut pool = self.pool.lock().expect(ERR_POISONED_LOCK);
217        pool.remove_mut(inner);
218    }
219}
220
221#[cfg(test)]
222mod tests {
223    use std::cell::Cell;
224
225    use static_assertions::{assert_impl_all, assert_not_impl_any};
226
227    use super::*;
228
229    // u32 is Sync, so PooledMut<u32> should be Send (but not Sync).
230    assert_impl_all!(PooledMut<u32>: Send);
231    assert_not_impl_any!(PooledMut<u32>: Sync);
232
233    // Cell is Send but not Sync, so PooledMut<Cell> should be neither Send nor Sync.
234    assert_not_impl_any!(PooledMut<Cell<u32>>: Send, Sync);
235
236    // We expect no destructor because we treat it as `Copy` in our own Drop::drop().
237    assert_not_impl_any!(RawPooledMut<()>: Drop);
238}