diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index afc7e1093..36b0e75e3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -38,6 +38,7 @@ env:
#
# This excludes `header-translator`, `test-assembly`, `tests` and `test-ui`.
PUBLIC_CRATES: >-
+ --package=dispatch2
--package=block2
--package=objc2
--package=objc2-encode
@@ -113,12 +114,12 @@ jobs:
target: armv7s-apple-ios
build-std: true
# `cc` works poorly when cross-compiling, so let's ignore `objc2-exception-helper` for now.
- args: --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_IOS_17 $INTERESTING_FEATURES -Zbuild-std
+ args: --package=dispatch2 --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_IOS_17 $INTERESTING_FEATURES -Zbuild-std
- name: visionOS Aarch64 simulator
target: aarch64-apple-visionos-sim
build-std: true
# `cc` works poorly when cross-compiling, so let's ignore `objc2-exception-helper` for now.
- args: --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_VISIONOS_1 $INTERESTING_FEATURES -Zbuild-std
+ args: --package=dispatch2 --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_VISIONOS_1 $INTERESTING_FEATURES -Zbuild-std
- name: GNUStep + exceptions
target: x86_64-unknown-linux-gnu
@@ -198,7 +199,7 @@ jobs:
key: cargo-${{ github.job }}-${{ matrix.name }}-${{ hashFiles('**/Cargo.lock') }}
- name: cargo check
- run: cargo check --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_MACOS_14 --features=all
+ run: cargo check --package=dispatch2 --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_MACOS_14 --features=all
env:
RUSTFLAGS: "--codegen=debuginfo=0" # Removed --deny=warnings
@@ -657,6 +658,7 @@ jobs:
RUNTIME_VERSION: gnustep-${{ matrix.libobjc2 }}
# Exclude `objc2-exception-helper`, for some reason that can't be tested directly on GNUStep
PUBLIC_CRATES: >-
+ --package=dispatch2
--package=block2
--package=objc2
--package=objc2-encode
@@ -688,7 +690,7 @@ jobs:
~/extern/lib
~/extern/include
# Change this key if we start caching more things
- key: extern-${{ github.job }}-${{ matrix.name }}-v1
+ key: extern-${{ github.job }}-${{ matrix.name }}-v2
- name: Setup environment
# These add to PATH-like variables, so they can always be set
@@ -721,6 +723,19 @@ jobs:
if: steps.extern-cache.outputs.cache-hit != 'true'
run: sudo apt-get -y install make cmake
+ - name: Install libdispatch
+ if: steps.extern-cache.outputs.cache-hit != 'true'
+ run: |
+ wget https://github.com/swiftlang/swift-corelibs-libdispatch/archive/refs/tags/swift-6.0.3-RELEASE.tar.gz
+ tar -xzf swift-6.0.3-RELEASE.tar.gz
+ cd swift-corelibs-libdispatch-swift-6.0.3-RELEASE
+
+ mkdir build
+ cd build
+ cmake -Wno-dev -DCMAKE_INSTALL_PREFIX=$HOME/extern ..
+ make install
+ ls -al $HOME/extern/*
+
- name: Install GNUStep libobjc2
if: steps.extern-cache.outputs.cache-hit != 'true'
run: |
diff --git a/Cargo.lock b/Cargo.lock
index d995a155c..c01268d49 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -180,6 +180,13 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
+[[package]]
+name = "dispatch2"
+version = "0.1.0"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "equivalent"
version = "1.0.1"
diff --git a/README.md b/README.md
index 0cf8b3fb4..5772c3860 100644
--- a/README.md
+++ b/README.md
@@ -11,10 +11,12 @@ The crates you're interested in is probably:
it, we [aim to have it](https://github.com/madsmtm/objc2/issues/393)).
- [`block2`], which provides bindings for Apple's C blocks, the
C-equivalent of a Rust closure.
+- [`dispatch2`], which provides bindings for Apple's Grand Central Dispatch.
[`objc2`]: ./crates/objc2
[`objc2-*`]: ./framework-crates
[`block2`]: ./crates/block2
+[`dispatch2`]: ./crates/dispatch2
## Contact Us
@@ -151,6 +153,8 @@ fork [here](https://github.com/SSheldon/rust-objc/issues/101):
These were created almost solely by [@SSheldon](https://github.com/SSheldon),
so a huge thanks for their fantastic work on these crates!
+Additionally, the `dispatch2` crate originally lived [here](https://github.com/marysaka/dispatch2).
+
This project also draws inspiration from:
- [`apple-sys`](https://github.com/youknowone/apple-sys)
- [`cacao`](https://github.com/ryanmcgrath/cacao)
@@ -163,6 +167,7 @@ This project also draws inspiration from:
- [`uikit-sys`](https://github.com/simlay/uikit-sys) and `@simlay`'s [Objective-C work on `bindgen`](https://rust-lang.github.io/rust-bindgen/objc.html)
- [`cidre`](https://github.com/yury/cidre)
- [the `apple-media` project](https://github.com/rust-media/apple-media-rs)
+- [`dispatch`](https://github.com/SSheldon/rust-dispatch)
Finally, this is by far not the only project that ever tried to interoperate with Objective-C; other languages have done so as well (to varying degrees of success):
- Swift: Built from the beginning for Objective-C interop, and is what `objc2` aspires to have feature-parity with (though will probably never reach). Truly beautifully designed language!
diff --git a/crates/block2/Cargo.toml b/crates/block2/Cargo.toml
index 56651ee6e..764949609 100644
--- a/crates/block2/Cargo.toml
+++ b/crates/block2/Cargo.toml
@@ -15,6 +15,9 @@ rust-version.workspace = true
repository.workspace = true
license = "MIT" # https://github.com/madsmtm/objc2/issues/23
+[lints]
+workspace = true
+
[features]
default = ["std"]
diff --git a/crates/block2/src/encoding.rs b/crates/block2/src/encoding.rs
index 52942970c..dc1ab2784 100644
--- a/crates/block2/src/encoding.rs
+++ b/crates/block2/src/encoding.rs
@@ -18,7 +18,7 @@ use objc2::encode::{EncodeArguments, EncodeReturn, Encoding};
/// assert_eq!(block_signature_string::<(i32, f32), u8>(), "C16@?0i8f12");
/// ```
#[allow(unused)]
-pub fn block_signature_string() -> CString
+pub(crate) fn block_signature_string() -> CString
where
A: EncodeArguments,
R: EncodeReturn,
diff --git a/crates/dispatch2/CHANGELOG.md b/crates/dispatch2/CHANGELOG.md
new file mode 100644
index 000000000..67b1d892c
--- /dev/null
+++ b/crates/dispatch2/CHANGELOG.md
@@ -0,0 +1,15 @@
+# Changelog
+
+Notable changes to this crate will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+
+## Unreleased - YYYY-MM-DD
+
+### Changed
+- Moved to the `objc2` project.
+
+
+## 0.1.0 - 2022-10-02
+
+Initial version.
diff --git a/crates/dispatch2/Cargo.toml b/crates/dispatch2/Cargo.toml
index 1f31d697c..6aaaff0af 100644
--- a/crates/dispatch2/Cargo.toml
+++ b/crates/dispatch2/Cargo.toml
@@ -1,18 +1,42 @@
[package]
name = "dispatch2"
-version = "0.1.0"
-authors = ["Mary "]
+version = "0.1.0" # Remember to update html_root_url in lib.rs
+description = "Bindings and wrappers for Apple's Grand Central Dispatch (GCD)"
+keywords = ["gcd", "macos", "ios", "dispatch", "libdispatch"]
+categories = [
+ "api-bindings",
+ "development-tools::ffi",
+ "os::macos-apis",
+ "external-ffi-bindings",
+]
+authors = ["Mads Marquart ", "Mary "]
+edition.workspace = true
+rust-version.workspace = true
+repository.workspace = true
license = "Apache-2.0 OR MIT"
-repository = "https://www.github.com/marysaka/dispatch2.git"
-homepage = "https://www.github.com/marysaka/dispatch2"
-description = "Bindings and wrappers for the Grand Central Dispatch (GCD)"
-keywords = ["gcd", "macOS", "iOS", "watchOS", "ipadOS"]
-categories = ["api-bindings", "development-tools::ffi", "os::macos-apis"]
-edition = "2021"
-exclude = [
- ".github"
-]
+[lints]
+workspace = true
[dependencies]
libc = "0.2"
+
+[package.metadata.docs.rs]
+default-target = "aarch64-apple-darwin"
+features = []
+targets = [
+ "aarch64-apple-darwin",
+ "x86_64-apple-darwin",
+ "aarch64-apple-ios",
+ "x86_64-apple-ios",
+ "aarch64-apple-tvos",
+ "aarch64-apple-watchos",
+ "aarch64-apple-ios-macabi",
+ "x86_64-unknown-linux-gnu",
+ "i686-unknown-linux-gnu",
+]
+
+[package.metadata.release]
+shared-version = false
+tag-prefix = "dispatch"
+enable-features = []
diff --git a/crates/dispatch2/README.md b/crates/dispatch2/README.md
index cbbae31a3..b486c0f2d 100644
--- a/crates/dispatch2/README.md
+++ b/crates/dispatch2/README.md
@@ -1,31 +1,17 @@
-# dispatch2
+# `dispatch2`
-Allows interaction with the [Apple Dispatch](https://developer.apple.com/documentation/dispatch) library in a safe and unsafe way.
+[![Latest version](https://badgen.net/crates/v/dispatch2)](https://crates.io/crates/dispatch2)
+[![License](https://badgen.net/static/license/MIT%20OR%20Apache%202.0/blue)](https://github.com/madsmtm/objc2/blob/master/LICENSE.txt)
+[![Documentation](https://docs.rs/dispatch2/badge.svg)](https://docs.rs/dispatch2/)
+[![CI](https://github.com/madsmtm/objc2/actions/workflows/ci.yml/badge.svg)](https://github.com/madsmtm/objc2/actions/workflows/ci.yml)
-## Usage
+Apple's Grand Central Dispatch interface in Rust.
-To use `dispatch2`, add this to your `Cargo.toml`:
+This crate provides a safe and sound interface to Apple's Grand Central
+dispatch, as well as the ability to drop into lower-level bindings.
-```toml
-[dependencies]
-dispatch2 = "0.1.0"
-```
+This README is kept intentionally small in an effort to consolidate the
+documentation, see [the Rust docs](https://docs.rs/dispatch2/) for more details.
-## Example
-
-```rust
-use dispatch2::{Queue, QueueAttribute};
-
-fn main() {
- let queue = Queue::new("example_queue", QueueAttribute::Serial);
- queue.exec_async(|| println!("Hello"));
- queue.exec_sync(|| println!("World"));
-}
-```
-
-## License
-
-dispatch2 is distributed under the terms of either the MIT license or the Apache
-License (Version 2.0), at the user's choice.
-
-See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT).
+This crate is part of the [`objc2` project](https://github.com/madsmtm/objc2),
+see that for related crates.
diff --git a/crates/dispatch2/TODO.md b/crates/dispatch2/TODO.md
index dd3ec4ce9..f96c1ba1d 100644
--- a/crates/dispatch2/TODO.md
+++ b/crates/dispatch2/TODO.md
@@ -6,7 +6,7 @@
- CI test on Windows using https://github.com/apple/swift-corelibs-libdispatch
- Safe wrapper for ``dispatch_source_*`` + ``set_target_queue/activate/suspend/resume`` for it
- Safe wrapper for ``dispatch_data_*``
-- Safe wrapper for ``dispatch_once_f`` (is that relevent?)
+- Safe wrapper for ``dispatch_once_f`` (is that relevant?)
- Safe wrapper for ``dispatch_get_context/dispatch_set_context`` (quite impossible without big overhead => wrap dispatch object destructor to release the boxed value)
- All blocks related bindings and ``dispatch_block_*`` functions with compat with ``block2`` on Apple platforms.
- Integrate conversion from SystemTime to dispatch_time_t via dispatch_walltime and safe APIs using that.
diff --git a/crates/dispatch2/src/ffi.rs b/crates/dispatch2/src/ffi.rs
index 756d6c5f4..61d2dbafc 100644
--- a/crates/dispatch2/src/ffi.rs
+++ b/crates/dispatch2/src/ffi.rs
@@ -8,7 +8,7 @@ use core::ffi::{c_char, c_int, c_long, c_uint, c_ulong, c_void};
macro_rules! create_opaque_type {
($type_name: ident, $typedef_name: ident) => {
#[repr(C)]
- #[derive(Debug)]
+ #[derive(Copy, Clone, Debug)]
#[allow(missing_docs)]
pub struct $type_name {
/// opaque value
@@ -32,7 +32,7 @@ macro_rules! enum_with_val {
}
impl ::core::fmt::Debug for $ident {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
$(&$ident::$variant => write!(f, "{}::{}", stringify!($ident), stringify!($variant)),)*
&$ident(v) => write!(f, "UNKNOWN({})", v),
@@ -191,14 +191,8 @@ enum_with_val! {
}
}
-#[cfg_attr(
- any(target_os = "macos", target_os = "ios", target_os = "tvos"),
- link(name = "System", kind = "dylib")
-)]
-#[cfg_attr(
- not(any(target_os = "macos", target_os = "ios", target_os = "tvos")),
- link(name = "dispatch", kind = "dylib")
-)]
+#[cfg_attr(target_vendor = "apple", link(name = "System", kind = "dylib"))]
+#[cfg_attr(not(target_vendor = "apple"), link(name = "dispatch", kind = "dylib"))]
extern "C" {
/// Increments the reference count (the retain count) of a dispatch object.
pub fn dispatch_retain(object: dispatch_object_t);
@@ -391,7 +385,7 @@ extern "C" {
) -> dispatch_queue_attr_t;
/// Creates a new dispatch queue to which you can submit blocks.
#[cfg_attr(
- any(target_os = "macos", target_os = "ios", target_os = "tvos"),
+ target_vendor = "apple",
link_name = "dispatch_queue_create_with_target$V2"
)]
pub fn dispatch_queue_create_with_target(
@@ -459,18 +453,12 @@ extern "C" {
pub fn dispatch_queue_get_specific(queue: dispatch_queue_t, key: *const c_void) -> *mut c_void;
/// Returns the value for the key associated with the current dispatch queue.
pub fn dispatch_get_specific(key: *const c_void) -> *mut c_void;
- #[cfg_attr(
- any(target_os = "macos", target_os = "ios", target_os = "tvos"),
- link_name = "dispatch_assert_queue$V2"
- )]
+ #[cfg_attr(target_vendor = "apple", link_name = "dispatch_assert_queue$V2")]
/// Generates an assertion if the current block is not running on the specified dispatch queue.
pub fn dispatch_assert_queue(queue: dispatch_queue_t);
/// Generates an assertion if the current block is not running as a barrier on the specified dispatch queue.
pub fn dispatch_assert_queue_barrier(queue: dispatch_queue_t);
- #[cfg_attr(
- any(target_os = "macos", target_os = "ios", target_os = "tvos"),
- link_name = "dispatch_assert_queue_not$V2"
- )]
+ #[cfg_attr(target_vendor = "apple", link_name = "dispatch_assert_queue_not$V2")]
/// Generates an assertion if the current block is executing on the specified dispatch queue.
pub fn dispatch_assert_queue_not(queue: dispatch_queue_t);
@@ -486,11 +474,11 @@ extern "C" {
pub static _dispatch_source_type_data_replace: dispatch_source_type_s;
pub static _dispatch_source_type_mach_send: dispatch_source_type_s;
pub static _dispatch_source_type_memorypressure: dispatch_source_type_s;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))]
+ #[cfg(target_vendor = "apple")]
pub static _dispatch_source_type_proc: dispatch_source_type_s;
pub static _dispatch_source_type_read: dispatch_source_type_s;
pub static _dispatch_source_type_timer: dispatch_source_type_s;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))]
+ #[cfg(target_vendor = "apple")]
pub static _dispatch_source_type_vnode: dispatch_source_type_s;
pub static _dispatch_source_type_write: dispatch_source_type_s;
/// Creates a new dispatch source to monitor low-level system events.
diff --git a/crates/dispatch2/src/group.rs b/crates/dispatch2/src/group.rs
index b2fc46efd..7fdcd44d4 100644
--- a/crates/dispatch2/src/group.rs
+++ b/crates/dispatch2/src/group.rs
@@ -30,7 +30,7 @@ impl Group {
}
// Safety: object cannot be null.
- let dispatch_object = unsafe { DispatchObject::new_owned(object as *mut _) };
+ let dispatch_object = unsafe { DispatchObject::new_owned(object.cast()) };
Some(Group { dispatch_object })
}
@@ -40,7 +40,7 @@ impl Group {
where
F: Send + FnOnce(),
{
- let work_boxed = Box::leak(Box::new(work)) as *mut _ as *mut c_void;
+ let work_boxed = Box::into_raw(Box::new(work)).cast::();
// Safety: All parameters cannot be null.
unsafe {
@@ -81,7 +81,7 @@ impl Group {
where
F: Send + FnOnce(),
{
- let work_boxed = Box::leak(Box::new(work)) as *mut _ as *mut c_void;
+ let work_boxed = Box::into_raw(Box::new(work)).cast::();
// Safety: All parameters cannot be null.
unsafe {
@@ -118,7 +118,8 @@ impl Group {
///
/// - Object shouldn't be released manually.
pub const unsafe fn as_raw(&self) -> dispatch_group_t {
- self.dispatch_object.as_raw()
+ // SAFETY: Upheld by caller
+ unsafe { self.dispatch_object.as_raw() }
}
}
diff --git a/crates/dispatch2/src/lib.rs b/crates/dispatch2/src/lib.rs
index 631833f75..8101a5391 100644
--- a/crates/dispatch2/src/lib.rs
+++ b/crates/dispatch2/src/lib.rs
@@ -1,26 +1,22 @@
-#![allow(unused_unsafe, unreachable_patterns)]
-#![deny(
- missing_docs,
- clippy::undocumented_unsafe_blocks,
- clippy::missing_safety_doc
-)]
-
-//!
-//! Apple Dispatch (Grand Central Dispatch)
+//! # Apple's Dispatch (Grand Central Dispatch)
//!
//! This crate allows interaction with the [Apple Dispatch](https://developer.apple.com/documentation/dispatch) library in a safe (``dispatch2`` module) and unsafe (``ffi`` module) way.
//!
-//! # Example:
+//! ## Example
//!
//! ```
//! use dispatch2::{Queue, QueueAttribute};
//!
-//! fn main() {
-//! let queue = Queue::new("example_queue", QueueAttribute::Serial);
-//! queue.exec_async(|| println!("Hello"));
-//! queue.exec_sync(|| println!("World"));
-//! }
+//! let queue = Queue::new("example_queue", QueueAttribute::Serial);
+//! queue.exec_async(|| println!("Hello"));
+//! queue.exec_sync(|| println!("World"));
//! ```
+#![allow(unreachable_patterns)]
+#![warn(missing_docs)]
+#![warn(clippy::undocumented_unsafe_blocks)]
+#![warn(clippy::missing_safety_doc)]
+// Update in Cargo.toml as well.
+#![doc(html_root_url = "https://docs.rs/dispatch2/0.1.0")]
use self::ffi::dispatch_qos_class_t;
diff --git a/crates/dispatch2/src/object.rs b/crates/dispatch2/src/object.rs
index d1a0371b1..5547ee2e7 100644
--- a/crates/dispatch2/src/object.rs
+++ b/crates/dispatch2/src/object.rs
@@ -52,7 +52,7 @@ impl DispatchObject {
// Safety: We own a reference to the object.
unsafe {
- dispatch_retain(result.object as *mut _);
+ dispatch_retain(result.object.cast());
}
result
@@ -63,14 +63,14 @@ impl DispatchObject {
where
F: Send + FnOnce(),
{
- let destructor_boxed = Box::leak(Box::new(destructor)) as *mut F as *mut _;
+ let destructor_boxed = Box::into_raw(Box::new(destructor)).cast();
// Safety: As this use the dispatch object's context, and because we need some way to wrap the Rust function, we set the context.
// Once the finalizer is executed, the context will be dangling.
// This isn't an issue as the context shall not be accessed after the dispatch object is destroyed.
unsafe {
- dispatch_set_context(self.object as *mut _, destructor_boxed);
- dispatch_set_finalizer_f(self.object as *mut _, function_wrapper::)
+ dispatch_set_context(self.object.cast(), destructor_boxed);
+ dispatch_set_finalizer_f(self.object.cast(), function_wrapper::)
}
}
@@ -84,9 +84,9 @@ impl DispatchObject {
return Err(TargetQueueError::ObjectAlreadyActive);
}
- // Safety: object and queue cannot be null.
+ // SAFETY: object and queue cannot be null.
unsafe {
- dispatch_set_target_queue(self.as_raw() as *mut _, queue.as_raw());
+ dispatch_set_target_queue(self.as_raw().cast(), queue.as_raw());
}
Ok(())
@@ -106,10 +106,10 @@ impl DispatchObject {
return Err(QualityOfServiceClassFloorError::InvalidRelativePriority);
}
- // Safety: Safe as relative_priority can only be valid.
+ // SAFETY: Safe as relative_priority can only be valid.
unsafe {
dispatch_set_qos_class_floor(
- self.as_raw() as *mut _,
+ self.as_raw().cast(),
dispatch_qos_class_t::from(qos_class),
relative_priority,
);
@@ -122,7 +122,7 @@ impl DispatchObject {
pub fn activate(&mut self) {
// Safety: object cannot be null.
unsafe {
- dispatch_activate(self.as_raw() as *mut _);
+ dispatch_activate(self.as_raw().cast());
}
self.is_activated = true;
@@ -132,7 +132,7 @@ impl DispatchObject {
pub fn suspend(&self) {
// Safety: object cannot be null.
unsafe {
- dispatch_suspend(self.as_raw() as *mut _);
+ dispatch_suspend(self.as_raw().cast());
}
}
@@ -140,7 +140,7 @@ impl DispatchObject {
pub fn resume(&self) {
// Safety: object cannot be null.
unsafe {
- dispatch_resume(self.as_raw() as *mut _);
+ dispatch_resume(self.as_raw().cast());
}
}
@@ -165,7 +165,7 @@ impl Drop for DispatchObject {
fn drop(&mut self) {
// Safety: We own a reference to the object.
unsafe {
- dispatch_release(self.object as *mut _);
+ dispatch_release(self.object.cast());
}
}
}
diff --git a/crates/dispatch2/src/queue.rs b/crates/dispatch2/src/queue.rs
index 3e6094452..898abb065 100644
--- a/crates/dispatch2/src/queue.rs
+++ b/crates/dispatch2/src/queue.rs
@@ -137,7 +137,7 @@ impl Queue {
assert!(!object.is_null(), "dispatch_queue_create shouldn't fail!");
// Safety: object cannot be null.
- let dispatch_object = unsafe { DispatchObject::new_owned(object as *mut _) };
+ let dispatch_object = unsafe { DispatchObject::new_owned(object.cast()) };
Queue {
dispatch_object,
@@ -161,7 +161,7 @@ impl Queue {
assert!(!object.is_null(), "dispatch_queue_create shouldn't fail!");
// Safety: object cannot be null.
- let dispatch_object = unsafe { DispatchObject::new_owned(object as *mut _) };
+ let dispatch_object = unsafe { DispatchObject::new_owned(object.cast()) };
// NOTE: dispatch_queue_create_with_target is in charge of retaining the target Queue.
@@ -171,7 +171,7 @@ impl Queue {
}
}
- /// Return a system-defined global concurrent [Queue] with the priority derivated from [GlobalQueueIdentifier].
+ /// Return a system-defined global concurrent [Queue] with the priority derived from [GlobalQueueIdentifier].
pub fn global_queue(identifier: GlobalQueueIdentifier) -> Self {
let raw_identifier = identifier.to_identifier();
@@ -184,7 +184,7 @@ impl Queue {
);
// Safety: object cannot be null.
- let dispatch_object = unsafe { DispatchObject::new_shared(object as *mut _) };
+ let dispatch_object = unsafe { DispatchObject::new_shared(object.cast()) };
Queue {
dispatch_object,
@@ -199,7 +199,7 @@ impl Queue {
{
assert!(!self.is_workloop, "exec_sync is invalid for WorkloopQueue");
- let work_boxed = Box::leak(Box::new(work)) as *mut F as *mut _;
+ let work_boxed = Box::into_raw(Box::new(work)).cast();
// Safety: object cannot be null and work is wrapped to avoid ABI incompatibility.
unsafe { dispatch_sync_f(self.as_raw(), work_boxed, function_wrapper::) }
@@ -210,7 +210,7 @@ impl Queue {
where
F: Send + FnOnce(),
{
- let work_boxed = Box::leak(Box::new(work)) as *mut F as *mut _;
+ let work_boxed = Box::into_raw(Box::new(work)).cast();
// Safety: object cannot be null and work is wrapped to avoid ABI incompatibility.
unsafe { dispatch_async_f(self.as_raw(), work_boxed, function_wrapper::) }
@@ -223,7 +223,7 @@ impl Queue {
{
let when =
dispatch_time_t::try_from(wait_time).map_err(|_| QueueAfterError::TimeOverflow)?;
- let work_boxed = Box::leak(Box::new(work)) as *mut F as *mut _;
+ let work_boxed = Box::into_raw(Box::new(work)).cast();
// Safety: object cannot be null and work is wrapped to avoid ABI incompatibility.
unsafe {
@@ -238,7 +238,7 @@ impl Queue {
where
F: Send + FnOnce(),
{
- let work_boxed = Box::leak(Box::new(work)) as *mut F as *mut _;
+ let work_boxed = Box::into_raw(Box::new(work)).cast();
// Safety: object cannot be null and work is wrapped to avoid ABI incompatibility.
unsafe { dispatch_barrier_async_f(self.as_raw(), work_boxed, function_wrapper::) }
@@ -249,7 +249,7 @@ impl Queue {
where
F: Send + FnOnce(),
{
- let work_boxed = Box::leak(Box::new(work)) as *mut F as *mut _;
+ let work_boxed = Box::into_raw(Box::new(work)).cast();
// Safety: object cannot be null and work is wrapped to avoid ABI incompatibility.
unsafe { dispatch_barrier_sync_f(self.as_raw(), work_boxed, function_wrapper::) }
@@ -260,7 +260,7 @@ impl Queue {
where
F: Send + FnOnce(),
{
- let work_boxed = Box::leak(Box::new(work)) as *mut F as *mut _;
+ let work_boxed = Box::into_raw(Box::new(work)).cast();
// Safety: object cannot be null and work is wrapped to avoid ABI incompatibility.
unsafe {
@@ -273,7 +273,7 @@ impl Queue {
where
F: Send + FnOnce(),
{
- let destructor_boxed = Box::leak(Box::new(destructor)) as *mut F as *mut _;
+ let destructor_boxed = Box::into_raw(Box::new(destructor)).cast();
// Safety: object cannot be null and destructor is wrapped to avoid ABI incompatibility.
unsafe {
@@ -334,7 +334,8 @@ impl Queue {
///
/// - Object shouldn't be released manually.
pub const unsafe fn as_raw(&self) -> dispatch_queue_t {
- self.dispatch_object.as_raw()
+ // SAFETY: Upheld by caller.
+ unsafe { self.dispatch_object.as_raw() }
}
}
@@ -361,7 +362,7 @@ impl WorkloopQueue {
assert!(!object.is_null(), "dispatch_queue_create shouldn't fail!");
// Safety: object cannot be null.
- let dispatch_object = unsafe { DispatchObject::new_owned(object as *mut _) };
+ let dispatch_object = unsafe { DispatchObject::new_owned(object.cast()) };
WorkloopQueue {
queue: Queue {
@@ -388,7 +389,8 @@ impl WorkloopQueue {
///
/// - Object shouldn't be released manually.
pub const unsafe fn as_raw(&self) -> dispatch_workloop_t {
- self.queue.as_raw() as dispatch_workloop_t
+ // SAFETY: Upheld by caller.
+ unsafe { self.queue.as_raw() as dispatch_workloop_t }
}
}
diff --git a/crates/dispatch2/src/semaphore.rs b/crates/dispatch2/src/semaphore.rs
index 443dd5feb..4d302cdfd 100644
--- a/crates/dispatch2/src/semaphore.rs
+++ b/crates/dispatch2/src/semaphore.rs
@@ -30,12 +30,12 @@ impl Semaphore {
}
// Safety: object cannot be null.
- let dispatch_object = unsafe { DispatchObject::new_owned(object as *mut _) };
+ let dispatch_object = unsafe { DispatchObject::new_owned(object.cast()) };
Some(Semaphore { dispatch_object })
}
- /// Attempt to aquire the [Semaphore] and return a [SemaphoreGuard].
+ /// Attempt to acquire the [Semaphore] and return a [SemaphoreGuard].
///
/// # Errors
///
@@ -72,7 +72,8 @@ impl Semaphore {
///
/// - Object shouldn't be released manually.
pub const unsafe fn as_raw(&self) -> dispatch_semaphore_t {
- self.dispatch_object.as_raw()
+ // SAFETY: Upheld by caller.
+ unsafe { self.dispatch_object.as_raw() }
}
}
diff --git a/crates/dispatch2/src/utils.rs b/crates/dispatch2/src/utils.rs
index 59e9301ff..5c6c08050 100644
--- a/crates/dispatch2/src/utils.rs
+++ b/crates/dispatch2/src/utils.rs
@@ -25,7 +25,7 @@ where
F: FnOnce(),
{
// Safety: we reconstruct from a Box.
- let work = unsafe { Box::from_raw(work_boxed as *mut F) };
+ let work = unsafe { Box::from_raw(work_boxed.cast::()) };
(*work)();
}