Skip to content

Commit 7a44ed9

Browse files
committed
Add NSThread and thread helper functions
1 parent b108d4a commit 7a44ed9

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

objc2-foundation/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1414
* Implement `PartialOrd` and `Ord` for `NSString` and `NSRange`.
1515
* Added `NSString::has_prefix` and `NSString::has_suffix`.
1616
* Added `NSRange` methods `new`, `is_empty`, `contains` and `end`.
17+
* Added `NSThread` object.
18+
* Added `is_multi_threaded` and `is_main_thread` helper functions.
1719

1820
### Changed
1921
* **BREAKING**: Removed the following helper traits in favor of inherent

objc2-foundation/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub use self::enumerator::{NSEnumerator, NSFastEnumeration, NSFastEnumerator};
3030
pub use self::object::NSObject;
3131
pub use self::range::NSRange;
3232
pub use self::string::NSString;
33+
pub use self::thread::{is_main_thread, is_multi_threaded, NSThread};
3334
pub use self::value::NSValue;
3435

3536
#[cfg(apple)]
@@ -52,4 +53,5 @@ mod enumerator;
5253
mod object;
5354
mod range;
5455
mod string;
56+
mod thread;
5557
mod value;

objc2-foundation/src/thread.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use core::ptr::NonNull;
2+
3+
use objc2::msg_send;
4+
use objc2::rc::{Id, Shared};
5+
use objc2::runtime::Bool;
6+
7+
use crate::NSObject;
8+
9+
object! {
10+
/// A thread of execution.
11+
///
12+
/// See [Apple's documentation](https://developer.apple.com/documentation/foundation/nsthread?language=objc).
13+
unsafe pub struct NSThread: NSObject;
14+
}
15+
16+
unsafe impl Send for NSThread {}
17+
unsafe impl Sync for NSThread {}
18+
19+
impl NSThread {
20+
/// Returns the [`NSThread`] object representing the current thread.
21+
pub fn current() -> Id<NSThread, Shared> {
22+
// currentThread is @property(strong), what does that mean?
23+
let obj: *mut Self = unsafe { msg_send![Self::class(), currentThread] };
24+
let obj = unsafe { NonNull::new_unchecked(obj) };
25+
unsafe { Id::retain(obj) }
26+
}
27+
28+
/// Returns the [`NSThread`] object representing the main thread.
29+
pub fn main() -> Id<NSThread, Shared> {
30+
// mainThread is @property(strong), what does that mean?
31+
let obj: *mut Self = unsafe { msg_send![Self::class(), mainThread] };
32+
let obj = unsafe { NonNull::new_unchecked(obj) };
33+
unsafe { Id::retain(obj) }
34+
}
35+
36+
/// Returns `true` if the thread is the main thread.
37+
pub fn is_main(&self) -> bool {
38+
let res: Bool = unsafe { msg_send![self, isMainThread] };
39+
res.is_true()
40+
}
41+
}
42+
43+
/// Whether the application is multithreaded according to Cocoa.
44+
pub fn is_multi_threaded() -> bool {
45+
let res: Bool = unsafe { msg_send![NSThread::class(), isMultiThreaded] };
46+
res.is_true()
47+
}
48+
49+
/// Whether the current thread is the main thread.
50+
pub fn is_main_thread() -> bool {
51+
let res: Bool = unsafe { msg_send![NSThread::class(), isMainThread] };
52+
res.is_true()
53+
}
54+
55+
#[cfg(test)]
56+
mod tests {
57+
use super::*;
58+
59+
#[test]
60+
fn test_main_thread() {
61+
let current = NSThread::current();
62+
let main = NSThread::main();
63+
64+
assert!(main.is_main());
65+
66+
if main == current {
67+
assert!(current.is_main());
68+
assert!(is_main_thread());
69+
} else {
70+
assert!(!current.is_main());
71+
assert!(!is_main_thread());
72+
}
73+
}
74+
75+
#[test]
76+
fn test_not_main_thread() {
77+
let res = std::thread::spawn(|| (is_main_thread(), NSThread::current().is_main()))
78+
.join()
79+
.unwrap();
80+
assert_eq!(res, (false, false));
81+
}
82+
}

0 commit comments

Comments
 (0)