Skip to content

Commit

Permalink
Various cleanups in dispatch2
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
madsmtm committed Dec 17, 2024
1 parent 84730a4 commit c7f5b7f
Show file tree
Hide file tree
Showing 16 changed files with 156 additions and 113 deletions.
23 changes: 19 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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: |
Expand Down
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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!
Expand Down
3 changes: 3 additions & 0 deletions crates/block2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

Expand Down
2 changes: 1 addition & 1 deletion crates/block2/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<A, R>() -> CString
pub(crate) fn block_signature_string<A, R>() -> CString
where
A: EncodeArguments,
R: EncodeReturn,
Expand Down
15 changes: 15 additions & 0 deletions crates/dispatch2/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
46 changes: 35 additions & 11 deletions crates/dispatch2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
[package]
name = "dispatch2"
version = "0.1.0"
authors = ["Mary <[email protected]>"]
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 <[email protected]>", "Mary <[email protected]>"]
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 = []
38 changes: 12 additions & 26 deletions crates/dispatch2/README.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion crates/dispatch2/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
30 changes: 9 additions & 21 deletions crates/dispatch2/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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),
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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);

Expand All @@ -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.
Expand Down
9 changes: 5 additions & 4 deletions crates/dispatch2/src/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
}
Expand All @@ -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::<c_void>();

// Safety: All parameters cannot be null.
unsafe {
Expand Down Expand Up @@ -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::<c_void>();

// Safety: All parameters cannot be null.
unsafe {
Expand Down Expand Up @@ -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() }
}
}

Expand Down
Loading

0 comments on commit c7f5b7f

Please sign in to comment.