You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Example:
We insist that all object instances exposed to foreign-language code be Sync and Send,
so that they’re safe to access regardless of the threading model of the calling code.
We do not allow thread-safety guarantees to be deferred to assumptions about how the code is called.
However, if an object is created on the main thread and all its methods are also called on the main thread, then even if the object does not satisfy Send, it is still thread-safe because it remains confined to a single thread.
@MainactorclassText{
// Make sure object only be used on main thread...
func get_text()->String{...}deinit{// class may be deallocated on other thread...so we need call `Drop::drop` on main thread
Task{@Mainactorin
// call `Drop::drop` here...
}}}
Since Swift 5.5, we have the @MainActor attribute. UniFFI can leverage this by adding @MainActor to the generated code for such cases.
Why
This feature is particularly useful for UI handling. Most native UI frameworks require updates to be performed on the main thread, meaning our Rust code may always run on the main thread. Allowing a !Send object could reduce unnecessary synchronization overhead.
Reminder
An object may be deallocated (deinit) on a different thread. Therefore, on the foreign language side, we need to ensure that Rust’s Drop() runs on the main thread.
Problem
I am not familar with C# and Kotlin, so I don't know whether they have equivalent of @Mainactor
The text was updated successfully, but these errors were encountered:
Rust has no concept of a "main thread", so I think something like this will need to be restricted to the bindings. In our current world, this implies we might need to nominate the special functions in uniffi.toml, then teach the Swift bindings to emit different code for those functions.
mhammond
changed the title
Feature: "Main thread" attribute for object
Swift Feature: "Main thread" attribute for object
Feb 13, 2025
Rust has no concept of a "main thread", so I think something like this will need to be restricted to the bindings. In our current world, this implies we might need to nominate the special functions in uniffi.toml, then teach the Swift bindings to emit different code for those functions.
You are right, I realize that Rust does not have “main thread”. But it is possible to lose the restriction of “Send” bound in some way. The user can guarantee thread safety when all operations happen on one thread. Currently, it seems that we just wrap all objects with Arc instead of giving the user choices.
I believe we are unlikely to offer a capability where the Rust side of the world is only safe if the user promises the foreign binding doesn't do unsafe things, but where they are capable of accidentally doing unsafe things.
The UniFFI user guide states:
However, if an object is created on the main thread and all its methods are also called on the main thread, then even if the object does not satisfy Send, it is still thread-safe because it remains confined to a single thread.
Rough Design
Rust side
Swift side
Since Swift 5.5, we have the
@MainActor
attribute. UniFFI can leverage this by adding@MainActor
to the generated code for such cases.Why
This feature is particularly useful for UI handling. Most native UI frameworks require updates to be performed on the main thread, meaning our Rust code may always run on the main thread. Allowing a
!Send
object could reduce unnecessary synchronization overhead.Reminder
An object may be deallocated (deinit) on a different thread. Therefore, on the foreign language side, we need to ensure that Rust’s
Drop()
runs on the main thread.Problem
I am not familar with C# and Kotlin, so I don't know whether they have equivalent of
@Mainactor
The text was updated successfully, but these errors were encountered: