Skip to content

Commit f798503

Browse files
committed
Various cleanups in dispatch2
- Add to CI. - Update to 2021 edition. - Support visionOS and watchOS. - Align Cargo.toml metadata with the rest of the project. - Fix typos. - Appease Clippy. - Prefer `Box::into_raw` over `Box::leak`. - Consolidate documentation. Part of #77.
1 parent 84730a4 commit f798503

16 files changed

+146
-112
lines changed

.github/workflows/ci.yml

+9-3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ env:
3838
#
3939
# This excludes `header-translator`, `test-assembly`, `tests` and `test-ui`.
4040
PUBLIC_CRATES: >-
41+
--package=dispatch2
4142
--package=block2
4243
--package=objc2
4344
--package=objc2-encode
@@ -113,12 +114,12 @@ jobs:
113114
target: armv7s-apple-ios
114115
build-std: true
115116
# `cc` works poorly when cross-compiling, so let's ignore `objc2-exception-helper` for now.
116-
args: --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_IOS_17 $INTERESTING_FEATURES -Zbuild-std
117+
args: --package=dispatch2 --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_IOS_17 $INTERESTING_FEATURES -Zbuild-std
117118
- name: visionOS Aarch64 simulator
118119
target: aarch64-apple-visionos-sim
119120
build-std: true
120121
# `cc` works poorly when cross-compiling, so let's ignore `objc2-exception-helper` for now.
121-
args: --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_VISIONOS_1 $INTERESTING_FEATURES -Zbuild-std
122+
args: --package=dispatch2 --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_VISIONOS_1 $INTERESTING_FEATURES -Zbuild-std
122123

123124
- name: GNUStep + exceptions
124125
target: x86_64-unknown-linux-gnu
@@ -198,7 +199,7 @@ jobs:
198199
key: cargo-${{ github.job }}-${{ matrix.name }}-${{ hashFiles('**/Cargo.lock') }}
199200

200201
- name: cargo check
201-
run: cargo check --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_MACOS_14 --features=all
202+
run: cargo check --package=dispatch2 --package=block2 --package=objc2 --package=objc2-encode --package=objc2-proc-macros $FRAMEWORKS_MACOS_14 --features=all
202203
env:
203204
RUSTFLAGS: "--codegen=debuginfo=0" # Removed --deny=warnings
204205

@@ -657,6 +658,7 @@ jobs:
657658
RUNTIME_VERSION: gnustep-${{ matrix.libobjc2 }}
658659
# Exclude `objc2-exception-helper`, for some reason that can't be tested directly on GNUStep
659660
PUBLIC_CRATES: >-
661+
--package=dispatch2
660662
--package=block2
661663
--package=objc2
662664
--package=objc2-encode
@@ -721,6 +723,10 @@ jobs:
721723
if: steps.extern-cache.outputs.cache-hit != 'true'
722724
run: sudo apt-get -y install make cmake
723725

726+
- name: Install libdispatch
727+
if: steps.extern-cache.outputs.cache-hit != 'true'
728+
run: sudo apt-get -y install libdispatch-dev
729+
724730
- name: Install GNUStep libobjc2
725731
if: steps.extern-cache.outputs.cache-hit != 'true'
726732
run: |

Cargo.lock

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ The crates you're interested in is probably:
1111
it, we [aim to have it](https://github.com/madsmtm/objc2/issues/393)).
1212
- [`block2`], which provides bindings for Apple's C blocks, the
1313
C-equivalent of a Rust closure.
14+
- [`dispatch2`], which provides bindings for Apple's Grand Central Dispatch.
1415

1516
[`objc2`]: ./crates/objc2
1617
[`objc2-*`]: ./framework-crates
1718
[`block2`]: ./crates/block2
19+
[`dispatch2`]: ./crates/dispatch2
1820

1921

2022
## Contact Us
@@ -151,6 +153,8 @@ fork [here](https://github.com/SSheldon/rust-objc/issues/101):
151153
These were created almost solely by [@SSheldon](https://github.com/SSheldon),
152154
so a huge thanks for their fantastic work on these crates!
153155

156+
Additionally, the `dispatch2` crate originally lived [here](https://github.com/marysaka/dispatch2).
157+
154158
This project also draws inspiration from:
155159
- [`apple-sys`](https://github.com/youknowone/apple-sys)
156160
- [`cacao`](https://github.com/ryanmcgrath/cacao)
@@ -163,6 +167,7 @@ This project also draws inspiration from:
163167
- [`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)
164168
- [`cidre`](https://github.com/yury/cidre)
165169
- [the `apple-media` project](https://github.com/rust-media/apple-media-rs)
170+
- [`dispatch`](https://github.com/SSheldon/rust-dispatch)
166171

167172
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):
168173
- 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!

crates/block2/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ rust-version.workspace = true
1515
repository.workspace = true
1616
license = "MIT" # https://github.com/madsmtm/objc2/issues/23
1717

18+
[lints]
19+
workspace = true
20+
1821
[features]
1922
default = ["std"]
2023

crates/block2/src/encoding.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use objc2::encode::{EncodeArguments, EncodeReturn, Encoding};
1818
/// assert_eq!(block_signature_string::<(i32, f32), u8>(), "C16@?0i8f12");
1919
/// ```
2020
#[allow(unused)]
21-
pub fn block_signature_string<A, R>() -> CString
21+
pub(crate) fn block_signature_string<A, R>() -> CString
2222
where
2323
A: EncodeArguments,
2424
R: EncodeReturn,

crates/dispatch2/CHANGELOG.md

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Changelog
2+
3+
Notable changes to this crate will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6+
7+
## Unreleased - YYYY-MM-DD
8+
9+
### Changed
10+
- Moved to the `objc2` project.
11+
12+
13+
## 0.1.0 - 2022-10-02
14+
15+
Initial version.

crates/dispatch2/Cargo.toml

+35-11
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,42 @@
11
[package]
22
name = "dispatch2"
3-
version = "0.1.0"
4-
authors = ["Mary <[email protected]>"]
3+
version = "0.1.0" # Remember to update html_root_url in lib.rs
4+
description = "Bindings and wrappers for Apple's Grand Central Dispatch (GCD)"
5+
keywords = ["gcd", "macos", "ios", "dispatch", "libdispatch"]
6+
categories = [
7+
"api-bindings",
8+
"development-tools::ffi",
9+
"os::macos-apis",
10+
"external-ffi-bindings",
11+
]
12+
authors = ["Mads Marquart <[email protected]>", "Mary <[email protected]>"]
13+
edition.workspace = true
14+
rust-version.workspace = true
15+
repository.workspace = true
516
license = "Apache-2.0 OR MIT"
6-
repository = "https://www.github.com/marysaka/dispatch2.git"
7-
homepage = "https://www.github.com/marysaka/dispatch2"
8-
description = "Bindings and wrappers for the Grand Central Dispatch (GCD)"
9-
keywords = ["gcd", "macOS", "iOS", "watchOS", "ipadOS"]
10-
categories = ["api-bindings", "development-tools::ffi", "os::macos-apis"]
11-
edition = "2021"
1217

13-
exclude = [
14-
".github"
15-
]
18+
[lints]
19+
workspace = true
1620

1721
[dependencies]
1822
libc = "0.2"
23+
24+
[package.metadata.docs.rs]
25+
default-target = "aarch64-apple-darwin"
26+
features = []
27+
targets = [
28+
"aarch64-apple-darwin",
29+
"x86_64-apple-darwin",
30+
"aarch64-apple-ios",
31+
"x86_64-apple-ios",
32+
"aarch64-apple-tvos",
33+
"aarch64-apple-watchos",
34+
"aarch64-apple-ios-macabi",
35+
"x86_64-unknown-linux-gnu",
36+
"i686-unknown-linux-gnu",
37+
]
38+
39+
[package.metadata.release]
40+
shared-version = false
41+
tag-prefix = "dispatch"
42+
enable-features = []

crates/dispatch2/README.md

+12-26
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,17 @@
1-
# dispatch2
1+
# `dispatch2`
22

3-
Allows interaction with the [Apple Dispatch](https://developer.apple.com/documentation/dispatch) library in a safe and unsafe way.
3+
[![Latest version](https://badgen.net/crates/v/dispatch2)](https://crates.io/crates/dispatch2)
4+
[![License](https://badgen.net/static/license/MIT%20OR%20Apache%202.0/blue)](https://github.com/madsmtm/objc2/blob/master/LICENSE.txt)
5+
[![Documentation](https://docs.rs/dispatch2/badge.svg)](https://docs.rs/dispatch2/)
6+
[![CI](https://github.com/madsmtm/objc2/actions/workflows/ci.yml/badge.svg)](https://github.com/madsmtm/objc2/actions/workflows/ci.yml)
47

5-
## Usage
8+
Apple's Grand Central Dispatch interface in Rust.
69

7-
To use `dispatch2`, add this to your `Cargo.toml`:
10+
This crate provides a safe and sound interface to Apple's Grand Central
11+
dispatch, as well as the ability to drop into lower-level bindings.
812

9-
```toml
10-
[dependencies]
11-
dispatch2 = "0.1.0"
12-
```
13+
This README is kept intentionally small in an effort to consolidate the
14+
documentation, see [the Rust docs](https://docs.rs/dispatch2/) for more details.
1315

14-
## Example
15-
16-
```rust
17-
use dispatch2::{Queue, QueueAttribute};
18-
19-
fn main() {
20-
let queue = Queue::new("example_queue", QueueAttribute::Serial);
21-
queue.exec_async(|| println!("Hello"));
22-
queue.exec_sync(|| println!("World"));
23-
}
24-
```
25-
26-
## License
27-
28-
dispatch2 is distributed under the terms of either the MIT license or the Apache
29-
License (Version 2.0), at the user's choice.
30-
31-
See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT).
16+
This crate is part of the [`objc2` project](https://github.com/madsmtm/objc2),
17+
see that for related crates.

crates/dispatch2/TODO.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
- CI test on Windows using https://github.com/apple/swift-corelibs-libdispatch
77
- Safe wrapper for ``dispatch_source_*`` + ``set_target_queue/activate/suspend/resume`` for it
88
- Safe wrapper for ``dispatch_data_*``
9-
- Safe wrapper for ``dispatch_once_f`` (is that relevent?)
9+
- Safe wrapper for ``dispatch_once_f`` (is that relevant?)
1010
- Safe wrapper for ``dispatch_get_context/dispatch_set_context`` (quite impossible without big overhead => wrap dispatch object destructor to release the boxed value)
1111
- All blocks related bindings and ``dispatch_block_*`` functions with compat with ``block2`` on Apple platforms.
1212
- Integrate conversion from SystemTime to dispatch_time_t via dispatch_walltime and safe APIs using that.

crates/dispatch2/src/ffi.rs

+9-21
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use core::ffi::{c_char, c_int, c_long, c_uint, c_ulong, c_void};
88
macro_rules! create_opaque_type {
99
($type_name: ident, $typedef_name: ident) => {
1010
#[repr(C)]
11-
#[derive(Debug)]
11+
#[derive(Copy, Clone, Debug)]
1212
#[allow(missing_docs)]
1313
pub struct $type_name {
1414
/// opaque value
@@ -32,7 +32,7 @@ macro_rules! enum_with_val {
3232
}
3333

3434
impl ::core::fmt::Debug for $ident {
35-
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
35+
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
3636
match self {
3737
$(&$ident::$variant => write!(f, "{}::{}", stringify!($ident), stringify!($variant)),)*
3838
&$ident(v) => write!(f, "UNKNOWN({})", v),
@@ -191,14 +191,8 @@ enum_with_val! {
191191
}
192192
}
193193

194-
#[cfg_attr(
195-
any(target_os = "macos", target_os = "ios", target_os = "tvos"),
196-
link(name = "System", kind = "dylib")
197-
)]
198-
#[cfg_attr(
199-
not(any(target_os = "macos", target_os = "ios", target_os = "tvos")),
200-
link(name = "dispatch", kind = "dylib")
201-
)]
194+
#[cfg_attr(target_vendor = "apple", link(name = "System", kind = "dylib"))]
195+
#[cfg_attr(not(target_vendor = "apple"), link(name = "dispatch", kind = "dylib"))]
202196
extern "C" {
203197
/// Increments the reference count (the retain count) of a dispatch object.
204198
pub fn dispatch_retain(object: dispatch_object_t);
@@ -391,7 +385,7 @@ extern "C" {
391385
) -> dispatch_queue_attr_t;
392386
/// Creates a new dispatch queue to which you can submit blocks.
393387
#[cfg_attr(
394-
any(target_os = "macos", target_os = "ios", target_os = "tvos"),
388+
target_vendor = "apple",
395389
link_name = "dispatch_queue_create_with_target$V2"
396390
)]
397391
pub fn dispatch_queue_create_with_target(
@@ -459,18 +453,12 @@ extern "C" {
459453
pub fn dispatch_queue_get_specific(queue: dispatch_queue_t, key: *const c_void) -> *mut c_void;
460454
/// Returns the value for the key associated with the current dispatch queue.
461455
pub fn dispatch_get_specific(key: *const c_void) -> *mut c_void;
462-
#[cfg_attr(
463-
any(target_os = "macos", target_os = "ios", target_os = "tvos"),
464-
link_name = "dispatch_assert_queue$V2"
465-
)]
456+
#[cfg_attr(target_vendor = "apple", link_name = "dispatch_assert_queue$V2")]
466457
/// Generates an assertion if the current block is not running on the specified dispatch queue.
467458
pub fn dispatch_assert_queue(queue: dispatch_queue_t);
468459
/// Generates an assertion if the current block is not running as a barrier on the specified dispatch queue.
469460
pub fn dispatch_assert_queue_barrier(queue: dispatch_queue_t);
470-
#[cfg_attr(
471-
any(target_os = "macos", target_os = "ios", target_os = "tvos"),
472-
link_name = "dispatch_assert_queue_not$V2"
473-
)]
461+
#[cfg_attr(target_vendor = "apple", link_name = "dispatch_assert_queue_not$V2")]
474462
/// Generates an assertion if the current block is executing on the specified dispatch queue.
475463
pub fn dispatch_assert_queue_not(queue: dispatch_queue_t);
476464

@@ -486,11 +474,11 @@ extern "C" {
486474
pub static _dispatch_source_type_data_replace: dispatch_source_type_s;
487475
pub static _dispatch_source_type_mach_send: dispatch_source_type_s;
488476
pub static _dispatch_source_type_memorypressure: dispatch_source_type_s;
489-
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))]
477+
#[cfg(target_vendor = "apple")]
490478
pub static _dispatch_source_type_proc: dispatch_source_type_s;
491479
pub static _dispatch_source_type_read: dispatch_source_type_s;
492480
pub static _dispatch_source_type_timer: dispatch_source_type_s;
493-
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))]
481+
#[cfg(target_vendor = "apple")]
494482
pub static _dispatch_source_type_vnode: dispatch_source_type_s;
495483
pub static _dispatch_source_type_write: dispatch_source_type_s;
496484
/// Creates a new dispatch source to monitor low-level system events.

crates/dispatch2/src/group.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl Group {
3030
}
3131

3232
// Safety: object cannot be null.
33-
let dispatch_object = unsafe { DispatchObject::new_owned(object as *mut _) };
33+
let dispatch_object = unsafe { DispatchObject::new_owned(object.cast()) };
3434

3535
Some(Group { dispatch_object })
3636
}
@@ -40,7 +40,7 @@ impl Group {
4040
where
4141
F: Send + FnOnce(),
4242
{
43-
let work_boxed = Box::leak(Box::new(work)) as *mut _ as *mut c_void;
43+
let work_boxed = Box::into_raw(Box::new(work)).cast::<c_void>();
4444

4545
// Safety: All parameters cannot be null.
4646
unsafe {
@@ -81,7 +81,7 @@ impl Group {
8181
where
8282
F: Send + FnOnce(),
8383
{
84-
let work_boxed = Box::leak(Box::new(work)) as *mut _ as *mut c_void;
84+
let work_boxed = Box::into_raw(Box::new(work)).cast::<c_void>();
8585

8686
// Safety: All parameters cannot be null.
8787
unsafe {
@@ -118,7 +118,8 @@ impl Group {
118118
///
119119
/// - Object shouldn't be released manually.
120120
pub const unsafe fn as_raw(&self) -> dispatch_group_t {
121-
self.dispatch_object.as_raw()
121+
// SAFETY: Upheld by caller
122+
unsafe { self.dispatch_object.as_raw() }
122123
}
123124
}
124125

crates/dispatch2/src/lib.rs

+11-15
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
1-
#![allow(unused_unsafe, unreachable_patterns)]
2-
#![deny(
3-
missing_docs,
4-
clippy::undocumented_unsafe_blocks,
5-
clippy::missing_safety_doc
6-
)]
7-
8-
//!
9-
//! Apple Dispatch (Grand Central Dispatch)
1+
//! # Apple's Dispatch (Grand Central Dispatch)
102
//!
113
//! 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.
124
//!
13-
//! # Example:
5+
//! ## Example
146
//!
157
//! ```
168
//! use dispatch2::{Queue, QueueAttribute};
179
//!
18-
//! fn main() {
19-
//! let queue = Queue::new("example_queue", QueueAttribute::Serial);
20-
//! queue.exec_async(|| println!("Hello"));
21-
//! queue.exec_sync(|| println!("World"));
22-
//! }
10+
//! let queue = Queue::new("example_queue", QueueAttribute::Serial);
11+
//! queue.exec_async(|| println!("Hello"));
12+
//! queue.exec_sync(|| println!("World"));
2313
//! ```
14+
#![allow(unreachable_patterns)]
15+
#![warn(missing_docs)]
16+
#![warn(clippy::undocumented_unsafe_blocks)]
17+
#![warn(clippy::missing_safety_doc)]
18+
// Update in Cargo.toml as well.
19+
#![doc(html_root_url = "https://docs.rs/dispatch2/0.1.0")]
2420

2521
use self::ffi::dispatch_qos_class_t;
2622

0 commit comments

Comments
 (0)