Skip to content

Commit c10819c

Browse files
committed
Make all structs transparent
1 parent 3ad1c96 commit c10819c

File tree

6 files changed

+71
-137
lines changed

6 files changed

+71
-137
lines changed

crates/dispatch2/src/group.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,20 @@ use core::{ffi::c_void, time::Duration};
66
use super::{ffi::*, function_wrapper, queue::Queue, rc::Retained, AsRawDispatchObject, WaitError};
77

88
/// Dispatch group.
9-
#[derive(Debug)]
9+
#[derive(Debug, Clone, Copy)]
1010
pub struct Group {
11-
inner: Retained<dispatch_group_s>,
11+
_inner: [u8; 0],
1212
}
1313

1414
impl Group {
1515
/// Creates a new [Group].
16-
pub fn new() -> Option<Self> {
16+
pub fn new() -> Option<Retained<Self>> {
1717
// Safety: valid to call.
1818
let object = unsafe { dispatch_group_create() };
19+
assert!(!object.is_null());
1920

20-
// Safety: retained accepts null pointer.
21-
let inner = unsafe { Retained::from_raw(object)? };
22-
23-
Some(Group { inner })
21+
// Safety: object must be valid.
22+
unsafe { Retained::from_raw(object.cast()) }
2423
}
2524

2625
/// Submit a function to a [Queue] and associates it with the [Group].
@@ -89,7 +88,11 @@ impl Group {
8988
dispatch_group_enter(self.as_raw());
9089
}
9190

92-
GroupGuard(self.clone(), false)
91+
let group =
92+
// Safety: group cannot be null.
93+
unsafe { Retained::retain(self.as_raw().cast()) }.expect("failed to retain semaphore");
94+
95+
GroupGuard(group, false)
9396
}
9497

9598
/// Get the raw [dispatch_group_t] value.
@@ -98,19 +101,7 @@ impl Group {
98101
///
99102
/// - Object shouldn't be released manually.
100103
pub fn as_raw(&self) -> dispatch_group_t {
101-
// Safety: Upheld by caller
102-
Retained::as_ptr(&self.inner).cast_mut()
103-
}
104-
}
105-
106-
impl Clone for Group {
107-
fn clone(&self) -> Self {
108-
Self {
109-
// Safety: pointer must be valid.
110-
inner: unsafe {
111-
Retained::retain(self.as_raw()).expect("failed to retain dispatch_group")
112-
},
113-
}
104+
self as *const Self as _
114105
}
115106
}
116107

@@ -128,7 +119,7 @@ unsafe impl Sync for Group {}
128119

129120
/// Dispatch group guard.
130121
#[derive(Debug)]
131-
pub struct GroupGuard(Group, bool);
122+
pub struct GroupGuard(Retained<Group>, bool);
132123

133124
impl GroupGuard {
134125
/// Explicitly indicates that the function in the [Group] finished executing.

crates/dispatch2/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ mod main_thread_bound;
4242
pub mod object;
4343
mod once;
4444
pub mod queue;
45-
mod rc;
45+
pub mod rc;
4646
pub mod semaphore;
4747
pub mod workloop;
4848

crates/dispatch2/src/queue.rs

Lines changed: 27 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Dispatch queue definition.
22
33
use alloc::{boxed::Box, ffi::CString};
4-
use core::{mem::ManuallyDrop, ptr::NonNull, time::Duration};
4+
use core::{ptr::NonNull, time::Duration};
55

66
use super::{
77
ffi::*, function_wrapper, rc::Retained, AsRawDispatchObject, QualityOfServiceClass,
@@ -86,34 +86,32 @@ impl Default for GlobalQueueIdentifier {
8686
}
8787

8888
/// Dispatch queue.
89-
#[derive(Debug)]
89+
#[repr(transparent)]
90+
#[derive(Debug, Copy, Clone)]
9091
pub struct Queue {
91-
inner: ManuallyDrop<Retained<dispatch_queue_s>>,
92-
is_global_queue: bool,
92+
_inner: [u8; 0],
9393
}
9494

9595
impl Queue {
9696
/// Create a new [Queue].
97-
pub fn new(label: &str, queue_attribute: QueueAttribute) -> Self {
97+
pub fn new(label: &str, queue_attribute: QueueAttribute) -> Retained<Self> {
9898
let label = CString::new(label).expect("Invalid label!");
9999

100100
// Safety: label and queue_attribute can only be valid.
101101
let object = unsafe {
102102
dispatch_queue_create(label.as_ptr(), dispatch_queue_attr_t::from(queue_attribute))
103103
};
104104

105-
// Safety: object cannot be null.
106-
let inner =
107-
unsafe { Retained::from_raw(object).expect("dispatch_queue_create shouldn't fail!") };
108-
109-
Queue {
110-
inner: ManuallyDrop::new(inner),
111-
is_global_queue: false,
112-
}
105+
// Safety: object must be valid.
106+
unsafe { Retained::from_raw(object.cast()) }.expect("dispatch_queue_create failed")
113107
}
114108

115109
/// Create a new [Queue] with a given target [Queue].
116-
pub fn new_with_target(label: &str, queue_attribute: QueueAttribute, target: &Queue) -> Self {
110+
pub fn new_with_target(
111+
label: &str,
112+
queue_attribute: QueueAttribute,
113+
target: &Queue,
114+
) -> Retained<Self> {
117115
let label = CString::new(label).expect("Invalid label!");
118116

119117
// Safety: label, queue_attribute and target can only be valid.
@@ -125,47 +123,31 @@ impl Queue {
125123
)
126124
};
127125

128-
// Safety: object cannot be null.
129-
let inner =
130-
unsafe { Retained::from_raw(object).expect("dispatch_queue_create shouldn't fail!") };
126+
assert!(!object.is_null());
131127

132128
// NOTE: dispatch_queue_create_with_target is in charge of retaining the target Queue.
133129

134-
Queue {
135-
inner: ManuallyDrop::new(inner),
136-
is_global_queue: false,
137-
}
130+
// Safety: object must be valid.
131+
unsafe { Retained::from_raw(object.cast()) }.expect("dispatch_queue_create failed")
138132
}
139133

140134
/// Return a system-defined global concurrent [Queue] with the priority derived from [GlobalQueueIdentifier].
141-
pub fn global_queue(identifier: GlobalQueueIdentifier) -> Self {
142-
let raw_identifier = identifier.to_identifier();
143-
135+
pub fn global_queue(identifier: GlobalQueueIdentifier) -> Retained<Self> {
144136
// Safety: raw_identifier cannot be invalid, flags is reserved.
145-
let object = unsafe { dispatch_get_global_queue(raw_identifier, 0) };
137+
let object = unsafe { dispatch_get_global_queue(identifier.to_identifier(), 0) };
138+
assert!(!object.is_null());
146139

147-
// Safety: object cannot be null.
148-
let inner = unsafe {
149-
Retained::from_raw(object.cast()).expect("dispatch_get_global_queue shouldn't fail!")
150-
};
151-
152-
Queue {
153-
inner: ManuallyDrop::new(inner),
154-
is_global_queue: true,
155-
}
140+
// Safety: object must be valid.
141+
unsafe { Retained::from_raw(object.cast()) }.expect("dispatch_get_global_queue failed")
156142
}
157143

158144
/// Return the main queue.
159-
pub fn main() -> Self {
160-
// Safety: object cannot be null.
161-
let inner = unsafe {
162-
Retained::from_raw(dispatch_get_main_queue().cast())
163-
.expect("dispatch_get_main_queue shouldn't fail!")
164-
};
165-
Queue {
166-
inner: ManuallyDrop::new(inner),
167-
is_global_queue: true,
168-
}
145+
pub fn main() -> Retained<Self> {
146+
let object = dispatch_get_main_queue();
147+
assert!(!object.is_null());
148+
149+
// Safety: object must be valid.
150+
unsafe { Retained::from_raw(object.cast()) }.expect("dispatch_get_main_queue failed")
169151
}
170152

171153
/// Submit a function for synchronous execution on the [Queue].
@@ -291,30 +273,7 @@ impl Queue {
291273
///
292274
/// - Object shouldn't be released manually.
293275
pub fn as_raw(&self) -> dispatch_queue_t {
294-
Retained::as_ptr(&self.inner).cast_mut()
295-
}
296-
}
297-
298-
impl Drop for Queue {
299-
fn drop(&mut self) {
300-
if !self.is_global_queue {
301-
// Safety: do not release global queues as they are singletons.
302-
let _ = unsafe { ManuallyDrop::take(&mut self.inner) };
303-
}
304-
}
305-
}
306-
307-
impl Clone for Queue {
308-
fn clone(&self) -> Self {
309-
Self {
310-
// Safety: pointer must be valid.
311-
inner: unsafe {
312-
ManuallyDrop::new(
313-
Retained::retain(self.as_raw()).expect("failed to retain dispatch_queue"),
314-
)
315-
},
316-
is_global_queue: self.is_global_queue,
317-
}
276+
self as *const Self as _
318277
}
319278
}
320279

crates/dispatch2/src/rc.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,37 @@ use super::ffi::*;
66

77
/// Smart pointer based on libdispatch reference counting system.
88
#[repr(transparent)]
9-
pub(crate) struct Retained<T: ?Sized> {
9+
pub struct Retained<T: ?Sized> {
1010
ptr: NonNull<T>,
1111
}
1212

1313
impl<T> Retained<T> {
1414
/// Create new smart pointer assuming the ownership over the object.
1515
/// The retain count will stay the same.
16-
pub(crate) unsafe fn from_raw(ptr: *mut T) -> Option<Self> {
16+
///
17+
/// # Safety
18+
/// Must be a valid pointer to the dispatch object having a retain count of +1.
19+
pub unsafe fn from_raw(ptr: *mut T) -> Option<Self> {
1720
NonNull::new(ptr).map(|ptr| Self { ptr })
1821
}
1922

2023
/// Create new smart pointer with shared ownership.
2124
/// Increments reference counter by 1.
25+
///
26+
/// # Safety
27+
/// Must be a valid pointer to the dispatch object.
2228
#[allow(unused)]
23-
pub(crate) unsafe fn retain(ptr: *mut T) -> Option<Self> {
29+
pub unsafe fn retain(ptr: *mut T) -> Option<Self> {
2430
NonNull::new(ptr).map(|ptr| {
2531
// Safety: upheld by the caller
2632
unsafe { dispatch_retain(ptr.as_ptr().cast()) };
2733
Self { ptr }
2834
})
2935
}
3036

37+
/// Returns the pointer to retained object.
3138
#[inline]
32-
pub(crate) fn as_ptr(this: &Self) -> *const T {
39+
pub fn as_ptr(this: &Self) -> *const T {
3340
this.ptr.as_ptr()
3441
}
3542
}

crates/dispatch2/src/semaphore.rs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@ use core::time::Duration;
55
use super::{ffi::*, rc::Retained, AsRawDispatchObject, WaitError};
66

77
/// Dispatch semaphore.
8-
#[derive(Debug)]
8+
#[repr(transparent)]
9+
#[derive(Debug, Clone, Copy)]
910
pub struct Semaphore {
10-
inner: Retained<dispatch_semaphore_s>,
11+
_inner: [u8; 0],
1112
}
1213

1314
impl Semaphore {
1415
/// Creates a new [Semaphore] with an initial value.
1516
///
1617
/// Returns None if value is negative or if creation failed.
17-
pub fn new(value: isize) -> Option<Self> {
18+
pub fn new(value: isize) -> Option<Retained<Self>> {
1819
// Per documentation creating a semaphore with a negative size isn't allowed.
1920
if value < 0 {
2021
return None;
@@ -24,11 +25,7 @@ impl Semaphore {
2425
let object = unsafe { dispatch_semaphore_create(value) };
2526

2627
// Safety: retained accepts null pointer.
27-
let dispatch_object = unsafe { Retained::from_raw(object)? };
28-
29-
Some(Semaphore {
30-
inner: dispatch_object,
31-
})
28+
unsafe { Retained::from_raw(object.cast()) }
3229
}
3330

3431
/// Attempt to acquire the [Semaphore] and return a [SemaphoreGuard].
@@ -48,8 +45,12 @@ impl Semaphore {
4845
// Safety: Semaphore cannot be null.
4946
let result = unsafe { dispatch_semaphore_wait(self.as_raw(), timeout) };
5047

48+
let sema =
49+
// Safety: semaphore cannot be null.
50+
unsafe { Retained::retain(self.as_raw().cast()) }.expect("failed to retain semaphore");
51+
5152
match result {
52-
0 => Ok(SemaphoreGuard(self.clone(), false)),
53+
0 => Ok(SemaphoreGuard(sema, false)),
5354
_ => Err(WaitError::Timeout),
5455
}
5556
}
@@ -60,18 +61,7 @@ impl Semaphore {
6061
///
6162
/// - Object shouldn't be released manually.
6263
pub fn as_raw(&self) -> dispatch_semaphore_t {
63-
Retained::as_ptr(&self.inner).cast_mut()
64-
}
65-
}
66-
67-
impl Clone for Semaphore {
68-
fn clone(&self) -> Self {
69-
Self {
70-
// Safety: pointer must be valid.
71-
inner: unsafe {
72-
Retained::retain(self.as_raw()).expect("failed to retain dispatch_semaphore_t")
73-
},
74-
}
64+
self as *const Self as _
7565
}
7666
}
7767

@@ -89,7 +79,7 @@ unsafe impl Sync for Semaphore {}
8979

9080
/// Dispatch semaphore guard.
9181
#[derive(Debug)]
92-
pub struct SemaphoreGuard(Semaphore, bool);
82+
pub struct SemaphoreGuard(Retained<Semaphore>, bool);
9383

9484
impl SemaphoreGuard {
9585
/// Release the [Semaphore].

0 commit comments

Comments
 (0)