File tree Expand file tree Collapse file tree 4 files changed +37
-0
lines changed Expand file tree Collapse file tree 4 files changed +37
-0
lines changed Original file line number Diff line number Diff line change @@ -10,6 +10,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
10
10
11
11
## icrate Unreleased - YYYY-MM-DD
12
12
13
+ ### Added
14
+ * Added ` MainThreadMarker ` ` From ` implementation for ` MainThreadOnly ` types.
15
+
13
16
### Changed
14
17
* Moved the ` ns_string! ` macro to ` icrate::Foundation::ns_string ` . The old
15
18
location in the crate root is deprecated.
Original file line number Diff line number Diff line change @@ -8,6 +8,7 @@ use crate::common::*;
8
8
use crate :: Foundation :: NSThread ;
9
9
10
10
use objc2:: msg_send_id;
11
+ use objc2:: mutability:: IsMainThreadOnly ;
11
12
12
13
unsafe impl Send for NSThread { }
13
14
unsafe impl Sync for NSThread { }
@@ -191,6 +192,23 @@ impl MainThreadMarker {
191
192
}
192
193
}
193
194
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
+
194
212
impl fmt:: Debug for MainThreadMarker {
195
213
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
196
214
f. debug_tuple ( "MainThreadMarker" ) . finish ( )
Original file line number Diff line number Diff line change @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
6
7
7
## Unreleased - YYYY-MM-DD
8
8
9
+ ### Added
10
+ * Added ` mutability::IsMainThreadOnly ` .
11
+
12
+
9
13
## 0.4.1 - 2023-07-31
10
14
11
15
### Added
Original file line number Diff line number Diff line change @@ -190,6 +190,9 @@ pub struct InteriorMutable {
190
190
///
191
191
/// This is commonly used in GUI code like `AppKit` and `UIKit`, e.g.
192
192
/// `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.
193
196
//
194
197
// While Xcode's Main Thread Checker doesn't report `alloc` and `dealloc` as
195
198
// unsafe from other threads, things like `NSView` and `NSWindow` still do a
@@ -308,6 +311,15 @@ impl<T: ?Sized + ClassType> IsAllocableAnyThread for T where
308
311
pub trait IsMutable : ClassType { }
309
312
impl < T : ?Sized + ClassType > IsMutable for T where T :: Mutability : private:: MutabilityIsMutable { }
310
313
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
+ // Note: MainThreadMarker::from relies on this.
320
+ pub trait IsMainThreadOnly : ClassType { }
321
+ impl < T : ?Sized + ClassType < Mutability = MainThreadOnly > > IsMainThreadOnly for T { }
322
+
311
323
#[ cfg( test) ]
312
324
mod tests {
313
325
use super :: * ;
You can’t perform that action at this time.
0 commit comments