Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dealing with other threads in dioxus #1806

Closed
ealmloff opened this issue Jan 10, 2024 · 1 comment
Closed

Dealing with other threads in dioxus #1806

ealmloff opened this issue Jan 10, 2024 · 1 comment
Labels
enhancement New feature or request signals Related to the signals crate

Comments

@ealmloff
Copy link
Member

ealmloff commented Jan 10, 2024

Specific Demand

Many desktop and liveview applications need to handle communicating with other threads. We should provide a recommended way to handle communicating with other threads. This would replace use_rw from dioxus std

Implement Suggestion

There are three main options:

Force users to use channels everywhere and not pass reactive state.

You can communicate with another thread today with a tokio or std channel. We could make this the official solution and not introduce any sync reactive state.

This has the benefit of not introducing any new APIs to signals, but it can introduce a lot of boilerplate to user apps. To mutate state, you need to create and send a message which could encourage extra boilerplate instead of mutating the state directly (like this message enum)

Make signals generic over Send + Sync (#1594)

This introduces a generic for the backing storage of signals. Signal<T> is an alias for Signal<T, UnSyncStorage> and Sync signals are Signal<T, SyncStorage>.

This has the benefit of not introducing any overhead for normal non-sync signals, but it introduces more generics into library code. A component that used to take Signal<T>, now may want to opt into taking Signal<T, S> where S is the storage type

This also allows libraries to create optionally Send+Sync components like this:

#[component]
fn MyComponents<S: Storage<u32>>(cx: Scope, state: Signal<u32, S>) -> Element {

}

This also allows libraries to create optionally Send+Sync state:

struct MyUseFuture<T, S: Storage<T>> {
    state: Option<Signal<T, S>>,
}

MyUseFuture can be either !Send or Send.

The extra generic could be removed with the impl approach in #1805

Create a separate sync signal type that you can convert normal signals to at runtime if T is send

This introduces a new SyncSignal type that can be created by upgrading a normal Signal to opt into more locking overhead.

This has the benefit of not introducing any new generics for libraries. If a library wants to accept a signal and doesn't care about syncness, they can accept a normal Signal and users can pass in either a downgraded SyncSignal or a Signal.

There will be some additional overhead to check the lock type of a Signal any time you interact with it. Signal handles to SyncSignals will need to go through two locks to get the inner value

This also allows libraries to create optionally Send+Sync components like this:

#[component]
fn MyComponents(cx: Scope, state: Signal<u32>) -> Element {

}

This also allows libraries to create optionally Send+Sync state like this:

struct MyUseFuture<T> {
    state: Option<Signal<T>>,
}

impl<T> MyUseFuture<T> {
    fn upgrade(&self) -> MySyncUseFuture<T> {}
}

struct MySyncUseFuture<T> {
    state: Option<SyncSignal<T>>,
}

impl<T> MySyncUseFuture<T> {
    fn downgrade(&self) -> MyUseFuture<T> {}
}
@ealmloff ealmloff added enhancement New feature or request signals Related to the signals crate labels Jan 10, 2024
@ealmloff
Copy link
Member Author

Signals that are generic over Send + Sync was merged in #1791

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request signals Related to the signals crate
Projects
None yet
Development

No branches or pull requests

1 participant