The default handle type wraps its data in a Mutex in order to ensure that the data is safe to access from multiple threads on the C# side. However, this adds overhead in cases where an object may only be used from a single thread. For example, in Unity games the vast majority of script code will only ever run on the main thread, so the extra synchronization is unnecessary overhead.
For these cases, it would be good to offer an alternative that verifies that the data is only ever accessed from the thread it was created on, but otherwise performs no synchronization. The fragile crate provides an example of types that do this. This article also talks about taking a similar approach.
There are two ways that we could support this:
Add an attribute to the type declaration in rust, e.g. #[cs_bindgen(not_sync)]. This would cause the generated code to use a non-sync handle.
Support both sync and non-sync handles for each Rust type, and provide some way for users of the C# bindings to choose which to use an on a case-by-case basis.
The latter approach would be ideal because it means that any given handle type could be used in either context without needing any changes on the Rust side. Some design work is needed in order to figure out the best approach, though.
The default handle type wraps its data in a
Mutex
in order to ensure that the data is safe to access from multiple threads on the C# side. However, this adds overhead in cases where an object may only be used from a single thread. For example, in Unity games the vast majority of script code will only ever run on the main thread, so the extra synchronization is unnecessary overhead.For these cases, it would be good to offer an alternative that verifies that the data is only ever accessed from the thread it was created on, but otherwise performs no synchronization. The fragile crate provides an example of types that do this. This article also talks about taking a similar approach.
There are two ways that we could support this:
#[cs_bindgen(not_sync)]
. This would cause the generated code to use a non-sync handle.The latter approach would be ideal because it means that any given handle type could be used in either context without needing any changes on the Rust side. Some design work is needed in order to figure out the best approach, though.