Skip to content

Commit 7f0b60e

Browse files
authored
Merge pull request #491 from madsmtm/main-thread-refactoring
Change a few things in our main thread utilities
2 parents 342675f + aa13544 commit 7f0b60e

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

crates/icrate/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1010

1111
## icrate Unreleased - YYYY-MM-DD
1212

13+
### Added
14+
* Added `MainThreadMarker` `From` implementation for `MainThreadOnly` types.
15+
1316
### Changed
1417
* Moved the `ns_string!` macro to `icrate::Foundation::ns_string`. The old
1518
location in the crate root is deprecated.
@@ -18,6 +21,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1821
- `refitAccelerationStructure_descriptor_destination_scratchBuffer_scratchBufferOffset`
1922
- `refitAccelerationStructure_descriptor_destination_scratchBuffer_scratchBufferOffset_options`
2023

24+
### Removed
25+
* **BREAKING**: Removed the `MainThreadMarker` argument from the closure
26+
passed to `MainThreadBound::get_on_main`.
27+
2128

2229
## icrate 0.0.4 - 2023-07-31
2330

crates/icrate/src/Foundation/additions/thread.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::common::*;
88
use crate::Foundation::NSThread;
99

1010
use objc2::msg_send_id;
11+
use objc2::mutability::IsMainThreadOnly;
1112

1213
unsafe impl Send for NSThread {}
1314
unsafe impl Sync for NSThread {}
@@ -191,6 +192,23 @@ impl MainThreadMarker {
191192
}
192193
}
193194

195+
/// Get a [`MainThreadMarker`] from a main-thread-only object.
196+
///
197+
/// This function exists purely in the type-system, and will always
198+
/// succeed at runtime.
199+
impl<T: ?Sized + IsMainThreadOnly> From<&T> for MainThreadMarker {
200+
#[inline]
201+
fn from(_obj: &T) -> Self {
202+
// SAFETY: Objects which are `IsMainThreadOnly` are guaranteed
203+
// `!Send + !Sync` and are only constructible on the main thread.
204+
//
205+
// Since we hold a reference to such an object, and we know it cannot
206+
// now possibly be on another thread than the main, we know that the
207+
// current thread is the main thread.
208+
unsafe { Self::new_unchecked() }
209+
}
210+
}
211+
194212
impl fmt::Debug for MainThreadMarker {
195213
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196214
f.debug_tuple("MainThreadMarker").finish()
@@ -311,10 +329,10 @@ impl<T> MainThreadBound<T> {
311329
#[inline]
312330
pub fn get_on_main<F, R>(&self, f: F) -> R
313331
where
314-
F: Send + FnOnce(&T, MainThreadMarker) -> R,
332+
F: Send + FnOnce(&T) -> R,
315333
R: Send,
316334
{
317-
MainThreadMarker::run_on_main(|mtm| f(self.get(mtm), mtm))
335+
MainThreadMarker::run_on_main(|mtm| f(self.get(mtm)))
318336
}
319337

320338
/// Access the item mutably on the main thread.
@@ -323,10 +341,10 @@ impl<T> MainThreadBound<T> {
323341
#[inline]
324342
pub fn get_on_main_mut<F, R>(&mut self, f: F) -> R
325343
where
326-
F: Send + FnOnce(&mut T, MainThreadMarker) -> R,
344+
F: Send + FnOnce(&mut T) -> R,
327345
R: Send,
328346
{
329-
MainThreadMarker::run_on_main(|mtm| f(self.get_mut(mtm), mtm))
347+
MainThreadMarker::run_on_main(|mtm| f(self.get_mut(mtm)))
330348
}
331349
}
332350

crates/objc2/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77
## Unreleased - YYYY-MM-DD
88

9+
### Added
10+
* Added `mutability::IsMainThreadOnly`.
11+
12+
913
## 0.4.1 - 2023-07-31
1014

1115
### Added

crates/objc2/src/mutability.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ pub struct InteriorMutable {
190190
///
191191
/// This is commonly used in GUI code like `AppKit` and `UIKit`, e.g.
192192
/// `UIWindow` is only usable from the application's main thread.
193+
///
194+
/// It is unsound to implement [`Send`] or [`Sync`] on a type with this
195+
/// mutability.
193196
//
194197
// While Xcode's Main Thread Checker doesn't report `alloc` and `dealloc` as
195198
// unsafe from other threads, things like `NSView` and `NSWindow` still do a
@@ -308,6 +311,19 @@ impl<T: ?Sized + ClassType> IsAllocableAnyThread for T where
308311
pub trait IsMutable: ClassType {}
309312
impl<T: ?Sized + ClassType> IsMutable for T where T::Mutability: private::MutabilityIsMutable {}
310313

314+
/// Marker trait for classes that are only available on the main thread.
315+
///
316+
/// This is implemented for classes whose [`ClassType::Mutability`] is one of:
317+
/// - [`MainThreadOnly`].
318+
///
319+
/// Since `MainThreadOnly` types must be `!Send` and `!Sync`, if you hold a
320+
/// type that implements this trait, then you're guaranteed to be on the main
321+
/// thread.
322+
//
323+
// Note: MainThreadMarker::from relies on this.
324+
pub trait IsMainThreadOnly: ClassType {}
325+
impl<T: ?Sized + ClassType<Mutability = MainThreadOnly>> IsMainThreadOnly for T {}
326+
311327
#[cfg(test)]
312328
mod tests {
313329
use super::*;

0 commit comments

Comments
 (0)