Struct objc2_foundation::MainThreadMarker

source ·
pub struct MainThreadMarker { /* private fields */ }
Expand description

A marker type taken by functions that can only be executed on the main thread.

By design, this is neither Send nor Sync, and can only be created on the main thread, meaning that if you’re holding this, you know you’re running on the main thread.

See the following links for more information on main-thread-only APIs:

§Main Thread Checker

Xcode provides a tool called the “Main Thread Checker” which verifies that UI APIs are being used from the correct thread. This is not as principled as MainThreadMarker, but is helpful for catching mistakes.

You can use this tool on macOS by loading libMainThreadChecker.dylib into your process using DYLD_INSERT_LIBRARIES:

DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/usr/lib/libMainThreadChecker.dylib MTC_RESET_INSERT_LIBRARIES=0 cargo run

If you’re not running your binary through Cargo, you can omit MTC_RESET_INSERT_LIBRARIES.

DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/usr/lib/libMainThreadChecker.dylib target/debug/myapp

If you’re developing for iOS, you probably better off enabling the tool in Xcode’s own UI.

See this excellent blog post for details on further configuration options.

§Examples

Use when designing APIs that are only safe to use on the main thread:

use objc2_foundation::{MainThreadMarker, NSObject};
use objc2::msg_send;

// This action requires the main thread, so we take a marker as parameter.
// It signals clearly to users "this requires the main thread".
unsafe fn do_thing(obj: *const NSObject, _mtm: MainThreadMarker) {
    msg_send![obj, someActionThatRequiresTheMainThread]
}

// Usage

// Create a new marker. This requires the `"NSThread"` feature.
// If that is not available, create the marker unsafely with
// `new_unchecked`, after having checked that the thread is the main one
// through other means.
#[cfg(feature = "NSThread")]
let mtm = MainThreadMarker::new().expect("must be on the main thread");
#[cfg(not(feature = "NSThread"))]
let mtm = unsafe { MainThreadMarker::new_unchecked() };
unsafe { do_thing(obj, mtm) }

Implementations§

source§

impl MainThreadMarker

source

pub fn new() -> Option<Self>

Available on crate feature NSThread only.

Construct a new MainThreadMarker.

Returns None if the current thread was not the main thread.

source

pub unsafe fn new_unchecked() -> Self

Construct a new MainThreadMarker without first checking whether the current thread is the main one.

§Safety

The current thread must be the main thread.

Alternatively, you may create this briefly if you know that a an API is safe in a specific case, but is not marked so. If you do that, you must ensure that any use of the marker is actually safe to do from another thread than the main one.

source

pub fn alloc<T: ClassType>(self) -> Allocated<T>

Allocate a new instance of the specified class on the main thread.

This is essentially the same as ClassType::alloc, the difference being that it is also callable with classes that can only be used on the main thread.

§Example

Create an object on the main thread.

use objc2_foundation::MainThreadMarker;
use objc2_app_kit::NSView as SomeClass; // An example class
use objc2::rc::Retained;
use objc2::msg_send_id;

let mtm = MainThreadMarker::new().expect("must be on the main thread");

// _All_ objects are safe to allocate on the main thread!
let obj = mtm.alloc::<SomeClass>();

// Though more knowledge is required for safe initialization
let obj: Retained<SomeClass> = unsafe { msg_send_id![obj, init] };
source

pub fn run_on_main<F, R>(f: F) -> R
where F: Send + FnOnce(MainThreadMarker) -> R, R: Send,

👎Deprecated: Use the free-standing function run_on_main instead
Available on crate features dispatch and NSThread only.

Submit the given closure to the runloop on the main thread.

Deprecated in favour of the free-standing function run_on_main.

Trait Implementations§

source§

impl Clone for MainThreadMarker

source§

fn clone(&self) -> MainThreadMarker

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for MainThreadMarker

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: ?Sized + IsMainThreadOnly> From<&T> for MainThreadMarker

Get a MainThreadMarker from a main-thread-only object.

This function exists purely in the type-system, and will always succeed at runtime.

source§

fn from(_obj: &T) -> Self

Converts to this type from the input type.
source§

impl Hash for MainThreadMarker

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for MainThreadMarker

source§

fn cmp(&self, other: &MainThreadMarker) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized + PartialOrd,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for MainThreadMarker

source§

fn eq(&self, other: &MainThreadMarker) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for MainThreadMarker

source§

fn partial_cmp(&self, other: &MainThreadMarker) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more
source§

impl Copy for MainThreadMarker

source§

impl Eq for MainThreadMarker

source§

impl StructuralPartialEq for MainThreadMarker

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> AutoreleaseSafe for T
where T: ?Sized,