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
Splitting the computation in your program into multiple threads to run multiple tasks at the same time can improve performance.
436
-
However, programming with threads has a reputation for being difficult. Rust’s type system and ownership model guarantee thread safety.
447
+
```toml
448
+
[dependencies]
449
+
fmodel-rust = { version = "0.8.2" }
450
+
```
451
+
452
+
If you don’t enable the feature, the **default** mode requires `Send` so your futures can safely hop between threads:
453
+
454
+
```rust
455
+
#[cfg(not(feature ="not-send-futures"))]
456
+
pubtraitEventRepository<C, E, Version, Error> {
457
+
/// Fetches current events, based on the command.
458
+
/// Desugared `async fn fetch_events(&self, command: &C) -> Result<Vec<(E, Version)>, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`.
459
+
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls. This is true even when one form has a Send bound.
/// Desugared `async fn save(&self, events: &[E], latest_version: &Option<Version>) -> Result<Vec<(E, Version)>, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`
466
+
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls. This is true even when one form has a Send bound.
/// Version provider. It is used to provide the version/sequence of the stream to wich this event belongs to. Optimistic locking is useing this version to check if the event is already saved.
470
+
/// Desugared `async fn version_provider(&self, event: &E) -> Result<Option<Version>, Error>;` to a normal `fn` that returns `impl Future`, and adds bound `Send`
471
+
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls. This is true even when one form has a Send bound.
Concurrency and async programming do not require a multi-threaded environment. You can run async tasks on a single-threaded executor, which allows you to write async code without the Send bound.
478
-
479
-
This approach has several benefits:
480
-
481
-
- Simpler code: No need for Arc, Mutex(RwLock), or other thread synchronization primitives for shared state.
526
+
```toml
527
+
[dependencies]
528
+
fmodel-rust = { version = "0.8.2", features = ["not-send-futures"] }
529
+
```
482
530
483
-
- Ergonomic references: You can freely use references within your async code without worrying about moving data across threads. 🤯
531
+
This mode removes the `Send` bound from async traits.
532
+
It works well with single-threaded runtimes (`tokio::task::LocalSet`) and allows using lighter primitives like `Rc<RefCell<T>>`.
484
533
485
-
- Efficient design: This model aligns with the “Thread-per-Core” pattern, letting you safely run multiple async tasks concurrently on a single thread.
534
+
```rust
535
+
#[cfg(feature ="not-send-futures")]
536
+
pubtraitEventRepository<C, E, Version, Error> {
537
+
/// Fetches current events, based on the command.
538
+
/// Desugared `async fn fetch_events(&self, command: &C) -> Result<Vec<(E, Version)>, Error>;` to a normal `fn` that returns `impl Future`.
539
+
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls.
/// Version provider. It is used to provide the version/sequence of the stream to wich this event belongs to. Optimistic locking is useing this version to check if the event is already saved.
547
+
/// Desugared `async fn version_provider(&self, event: &E) -> Result<Option<Version>, Error>;` to a normal `fn` that returns `impl Future`
548
+
/// You can freely move between the `async fn` and `-> impl Future` spelling in your traits and impls.
In short: you get all the power of async/await without the complexity of multi-threaded synchronization all the time.
553
+
This approach has several benefits:
488
554
489
-
Just switching to a [LocalExecutor](https://docs.rs/async-executor/latest/async_executor/struct.LocalExecutor.html) or something like Tokio [LocalSet](https://docs.rs/tokio/latest/tokio/task/struct.LocalSet.html) should be enough.
555
+
- Simpler code: No need for `Arc`, `Mutex/RwLock`, or other expensive thread synchronization primitives.
490
556
491
-
If you want to enable single-threaded, Send-free async support, you can enable the optional feature `not-send-futures` when adding fmodel-rust to your project:
557
+
- Efficient design: This model aligns with the “Thread-per-Core” pattern, letting you safely run multiple async tasks concurrently on a single thread.
492
558
493
-
```toml
494
-
[dependencies]
495
-
fmodel-rust = { version = "0.8.2", features = ["not-send-futures"] }
496
-
```
497
559
498
-
Example of the concurrent execution of the aggregate in single-threaded environment (**behind feature** - `Send` free `Futures`):
560
+
Example of the concurrent execution of the aggregate in single-threaded environment (`Send` free `Futures`):
0 commit comments