Skip to content

Commit 0cfd606

Browse files
committed
Use StrongPtr and WeakPtr from objc::rc
1 parent df7809c commit 0cfd606

File tree

4 files changed

+64
-133
lines changed

4 files changed

+64
-133
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ license = "MIT"
1313
exclude = [".gitignore"]
1414

1515
[dependencies]
16-
objc = "0.2"
16+
objc = "0.2.4"

src/id.rs

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,9 @@ use std::marker::PhantomData;
55
use std::ops::{Deref, DerefMut};
66

77
use objc::Message;
8+
use objc::rc::{StrongPtr, WeakPtr};
89
use objc::runtime::Object;
910

10-
#[link(name = "objc", kind = "dylib")]
11-
extern {
12-
fn objc_retain(obj: *mut Object) -> *mut Object;
13-
fn objc_release(obj: *mut Object);
14-
}
15-
16-
struct StrongPtr(*mut Object);
17-
18-
impl Drop for StrongPtr {
19-
fn drop(&mut self) {
20-
unsafe {
21-
objc_release(self.0);
22-
}
23-
}
24-
}
25-
2611
/// A type used to mark that a struct owns the object(s) it contains,
2712
/// so it has the sole references to them.
2813
pub enum Owned { }
@@ -65,7 +50,7 @@ impl<T, O> Id<T, O> where T: Message, O: Ownership {
6550
/// the caller must ensure the ownership is correct.
6651
pub unsafe fn from_ptr(ptr: *mut T) -> Id<T, O> {
6752
assert!(!ptr.is_null(), "Attempted to construct an Id from a null pointer");
68-
Id::new(StrongPtr(objc_retain(ptr as *mut Object)))
53+
Id::new(StrongPtr::retain(ptr as *mut Object))
6954
}
7055

7156
/// Constructs an `Id` from a pointer to a retained object; this won't
@@ -75,7 +60,7 @@ impl<T, O> Id<T, O> where T: Message, O: Ownership {
7560
/// the caller must ensure the ownership is correct.
7661
pub unsafe fn from_retained_ptr(ptr: *mut T) -> Id<T, O> {
7762
assert!(!ptr.is_null(), "Attempted to construct an Id from a null pointer");
78-
Id::new(StrongPtr(ptr as *mut Object))
63+
Id::new(StrongPtr::new(ptr as *mut Object))
7964
}
8065
}
8166

@@ -90,7 +75,7 @@ impl<T> Id<T, Owned> where T: Message {
9075
impl<T> Clone for Id<T, Shared> where T: Message {
9176
fn clone(&self) -> ShareId<T> {
9277
unsafe {
93-
Id::new(StrongPtr(objc_retain(self.ptr.0)))
78+
Id::new(self.ptr.clone())
9479
}
9580
}
9681
}
@@ -105,13 +90,13 @@ impl<T, O> Deref for Id<T, O> {
10590
type Target = T;
10691

10792
fn deref(&self) -> &T {
108-
unsafe { &*(self.ptr.0 as *mut T) }
93+
unsafe { &*(*self.ptr as *mut T) }
10994
}
11095
}
11196

11297
impl<T> DerefMut for Id<T, Owned> {
11398
fn deref_mut(&mut self) -> &mut T {
114-
unsafe { &mut *(self.ptr.0 as *mut T) }
99+
unsafe { &mut *(*self.ptr as *mut T) }
115100
}
116101
}
117102

@@ -141,25 +126,57 @@ impl<T, O> fmt::Debug for Id<T, O> where T: fmt::Debug {
141126

142127
impl<T, O> fmt::Pointer for Id<T, O> {
143128
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144-
fmt::Pointer::fmt(&self.ptr.0, f)
129+
fmt::Pointer::fmt(&self.ptr, f)
145130
}
146131
}
147132

148133
/// A convenient alias for a shared `Id`.
149134
pub type ShareId<T> = Id<T, Shared>;
150135

136+
/// A pointer type for a weak reference to an Objective-C reference counted
137+
/// object.
138+
pub struct WeakId<T> {
139+
ptr: WeakPtr,
140+
item: PhantomData<T>,
141+
}
142+
143+
impl<T> WeakId<T> where T: Message {
144+
/// Construct a new `WeakId` referencing the given `ShareId`.
145+
pub fn new(obj: &ShareId<T>) -> WeakId<T> {
146+
WeakId {
147+
ptr: obj.ptr.weak(),
148+
item: PhantomData,
149+
}
150+
}
151+
152+
/// Load a `ShareId` from the `WeakId` if the object still exists.
153+
/// Returns `None` if the object has been deallocated.
154+
pub fn load(&self) -> Option<ShareId<T>> {
155+
let obj = self.ptr.load();
156+
if obj.is_null() {
157+
None
158+
} else {
159+
Some(unsafe { Id::new(obj) })
160+
}
161+
}
162+
}
163+
164+
unsafe impl<T> Sync for WeakId<T> where T: Sync { }
165+
166+
unsafe impl<T> Send for WeakId<T> where T: Sync { }
167+
151168
#[cfg(test)]
152169
mod tests {
153-
use objc::runtime::{Class, Object};
154-
use super::Id;
170+
use objc::runtime::Object;
171+
use super::{Id, ShareId, WeakId};
155172

156173
fn retain_count(obj: &Object) -> usize {
157174
unsafe { msg_send![obj, retainCount] }
158175
}
159176

160177
#[test]
161178
fn test_clone() {
162-
let cls = Class::get("NSObject").unwrap();
179+
let cls = class!(NSObject);
163180
let obj: Id<Object> = unsafe {
164181
let obj: *mut Object = msg_send![cls, alloc];
165182
let obj: *mut Object = msg_send![obj, init];
@@ -177,4 +194,24 @@ mod tests {
177194
drop(obj);
178195
assert!(retain_count(&cloned) == 1);
179196
}
197+
198+
#[test]
199+
fn test_weak() {
200+
let cls = class!(NSObject);
201+
let obj: ShareId<Object> = unsafe {
202+
let obj: *mut Object = msg_send![cls, alloc];
203+
let obj: *mut Object = msg_send![obj, init];
204+
Id::from_retained_ptr(obj)
205+
};
206+
207+
let weak = WeakId::new(&obj);
208+
let strong = weak.load().unwrap();
209+
let strong_ptr: *const Object = &*strong;
210+
let obj_ptr: *const Object = &*obj;
211+
assert!(strong_ptr == obj_ptr);
212+
drop(strong);
213+
214+
drop(obj);
215+
assert!(weak.load().is_none());
216+
}
180217
}

src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ assert!(weak.load().is_none());
4242
#[macro_use]
4343
extern crate objc;
4444

45-
pub use id::{Id, Owned, Ownership, Shared, ShareId};
46-
pub use weak::WeakId;
45+
pub use id::{Id, Owned, Ownership, Shared, ShareId, WeakId};
4746

4847
mod id;
49-
mod weak;

src/weak.rs

Lines changed: 0 additions & 104 deletions
This file was deleted.

0 commit comments

Comments
 (0)