Skip to content

Commit 2cebfce

Browse files
committed
Add initial Owned pointer, the mutable version of Retained
1 parent b9f1849 commit 2cebfce

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed

src/rc/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,14 @@ assert!(weak.load().is_null());
4040
```
4141
*/
4242

43+
mod owned;
4344
mod retained;
4445
mod strong;
4546
mod weak;
4647
mod autorelease;
4748

4849
pub use self::retained::Retained;
50+
pub use self::owned::Owned;
4951
pub use self::strong::StrongPtr;
5052
pub use self::weak::WeakPtr;
5153
pub use self::autorelease::autoreleasepool;

src/rc/owned.rs

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
use core::marker::PhantomData;
2+
use core::ptr::{NonNull, drop_in_place};
3+
use core::mem;
4+
use core::ops::{DerefMut, Deref};
5+
use core::fmt;
6+
use core::hash;
7+
use core::borrow;
8+
9+
use super::Retained;
10+
use crate::runtime::{self, Object};
11+
12+
/// A smart pointer that strongly references and owns an Objective-C object.
13+
///
14+
/// The fact that we own the pointer means that we're safe to mutate it, hence
15+
/// why this implements [`DerefMut`].
16+
///
17+
/// This is guaranteed to have the same size as the underlying pointer.
18+
///
19+
/// TODO: Explain similarities to [`Box`].
20+
///
21+
/// TODO: Explain this vs. [`Retained`]
22+
#[repr(transparent)]
23+
pub struct Owned<T> {
24+
/// The pointer is always retained.
25+
pub(super) ptr: NonNull<T>, // Covariant
26+
phantom: PhantomData<T>, // Necessary for dropcheck
27+
}
28+
29+
// SAFETY: TODO
30+
unsafe impl<T: Send> Send for Owned<T> {}
31+
32+
// SAFETY: TODO
33+
unsafe impl<T: Sync> Sync for Owned<T> {}
34+
35+
impl<T> Owned<T> {
36+
#[inline]
37+
pub unsafe fn new(ptr: NonNull<T>) -> Self {
38+
Self {
39+
ptr,
40+
phantom: PhantomData,
41+
}
42+
}
43+
44+
// TODO: Unsure how the API should look...
45+
#[inline]
46+
pub unsafe fn retain(ptr: NonNull<T>) -> Self {
47+
Self::from_retained(Retained::retain(ptr))
48+
}
49+
50+
/// TODO
51+
///
52+
/// # Safety
53+
///
54+
/// The given [`Retained`] must be the only reference to the object
55+
/// anywhere in the program - even in other Objective-C code.
56+
#[inline]
57+
pub unsafe fn from_retained(obj: Retained<T>) -> Self {
58+
let ptr = mem::ManuallyDrop::new(obj).ptr;
59+
Self {
60+
ptr,
61+
phantom: PhantomData,
62+
}
63+
}
64+
}
65+
66+
// TODO: #[may_dangle]
67+
// https://doc.rust-lang.org/nightly/nomicon/dropck.html
68+
impl<T> Drop for Owned<T> {
69+
/// Releases the retained object
70+
///
71+
/// This is guaranteed to be the last destructor that runs, in contrast to
72+
/// [`Retained`], which means that we can run the [`Drop`] implementation
73+
/// on the contained object as well.
74+
#[inline]
75+
fn drop(&mut self) {
76+
let ptr = self.ptr;
77+
unsafe {
78+
drop_in_place(ptr.as_ptr());
79+
// Construct a new `Retained`, which will be dropped immediately
80+
Retained::new(ptr);
81+
};
82+
}
83+
}
84+
85+
// Note: `Clone` is not implemented for this!
86+
87+
impl<T> Deref for Owned<T> {
88+
type Target = T;
89+
90+
#[inline]
91+
fn deref(&self) -> &Self::Target {
92+
// SAFETY: TODO
93+
unsafe { self.ptr.as_ref() }
94+
}
95+
}
96+
97+
impl<T> DerefMut for Owned<T> {
98+
#[inline]
99+
fn deref_mut(&mut self) -> &mut Self::Target {
100+
// SAFETY: TODO
101+
unsafe { self.ptr.as_mut() }
102+
}
103+
}
104+
105+
// TODO: impl PartialEq, PartialOrd, Ord and Eq
106+
107+
impl<T: fmt::Display> fmt::Display for Owned<T> {
108+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109+
fmt::Display::fmt(&**self, f)
110+
}
111+
}
112+
113+
impl<T: fmt::Debug> fmt::Debug for Owned<T> {
114+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115+
fmt::Debug::fmt(&**self, f)
116+
}
117+
}
118+
119+
impl<T> fmt::Pointer for Owned<T> {
120+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121+
fmt::Pointer::fmt(&self.ptr.as_ptr(), f)
122+
}
123+
}
124+
125+
impl<T: hash::Hash> hash::Hash for Owned<T> {
126+
fn hash<H: hash::Hasher>(&self, state: &mut H) {
127+
(&**self).hash(state)
128+
}
129+
}
130+
131+
// TODO: impl Fn traits? See `boxed_closure_impls`
132+
133+
// TODO: CoerceUnsized
134+
135+
impl<T> borrow::Borrow<T> for Owned<T> {
136+
fn borrow(&self) -> &T {
137+
&**self
138+
}
139+
}
140+
141+
impl<T> borrow::BorrowMut<T> for Owned<T> {
142+
fn borrow_mut(&mut self) -> &mut T {
143+
&mut **self
144+
}
145+
}
146+
147+
impl<T> AsRef<T> for Owned<T> {
148+
fn as_ref(&self) -> &T {
149+
&**self
150+
}
151+
}
152+
153+
impl<T> AsMut<T> for Owned<T> {
154+
fn as_mut(&mut self) -> &mut T {
155+
&mut **self
156+
}
157+
}
158+
159+
// TODO: Comment on impl Unpin for Box
160+
impl<T> Unpin for Owned<T> {}

src/rc/retained.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use core::ops::Deref;
77
use core::ptr::NonNull;
88

99
use crate::runtime::{self, Object};
10+
use super::Owned;
1011

1112
/// A smart pointer that strongly references an object, ensuring it won't be
1213
/// deallocated.
@@ -209,6 +210,13 @@ impl<T> AsRef<T> for Retained<T> {
209210

210211
impl<T> Unpin for Retained<T> {}
211212

213+
impl<T> From<Owned<T>> for Retained<T> {
214+
fn from(obj: Owned<T>) -> Self {
215+
// SAFETY: TODO
216+
unsafe { Self::new(obj.ptr) }
217+
}
218+
}
219+
212220
#[cfg(test)]
213221
mod tests {
214222
use core::mem::size_of;

0 commit comments

Comments
 (0)