Skip to content

Commit c13e31f

Browse files
committed
docs: clarify Backend::Thread still uses async runtime internally
1 parent e386fa6 commit c13e31f

File tree

1 file changed

+30
-23
lines changed

1 file changed

+30
-23
lines changed

concurrency/src/tasks/gen_server.rs

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,22 @@ const DEFAULT_CALL_TIMEOUT: Duration = Duration::from_secs(5);
2525
/// |---------|-----------------|----------|-------------|
2626
/// | `Async` | Tokio task | Non-blocking I/O, async operations | Blocks runtime if sync code runs too long |
2727
/// | `Blocking` | Tokio blocking pool | Short blocking operations (file I/O, DNS) | Shared pool with limited threads |
28-
/// | `Thread` | Dedicated OS thread | Long-running blocking work, CPU-heavy tasks | Higher memory overhead per GenServer |
28+
/// | `Thread` | Dedicated OS thread with own runtime | Long-running services, isolation from main runtime | Higher memory overhead per GenServer |
29+
///
30+
/// **Note**: All backends use async internally. For fully synchronous code without any async
31+
/// runtime, use [`threads::GenServer`](crate::threads::GenServer) instead.
2932
///
3033
/// # Examples
3134
///
3235
/// ```ignore
3336
/// // For typical async workloads (HTTP handlers, database queries)
34-
/// let handle = MyServer::new().start(Backend::Async);
37+
/// let handle = MyServer::new().start();
3538
///
3639
/// // For occasional blocking operations (file reads, external commands)
37-
/// let handle = MyServer::new().start(Backend::Blocking);
40+
/// let handle = MyServer::new().start_with_backend(Backend::Blocking);
3841
///
3942
/// // For CPU-intensive or permanently blocking services
40-
/// let handle = MyServer::new().start(Backend::Thread);
43+
/// let handle = MyServer::new().start_with_backend(Backend::Thread);
4144
/// ```
4245
///
4346
/// # When to Use Each Backend
@@ -53,9 +56,10 @@ const DEFAULT_CALL_TIMEOUT: Duration = Duration::from_secs(5);
5356
/// - **Avoid when**: You need guaranteed thread availability or long-running blocks
5457
///
5558
/// ## `Backend::Thread`
56-
/// - **Advantages**: Complete isolation, no interference with async runtime
57-
/// - **Use when**: Long-running blocking work, singleton services, CPU-bound tasks
58-
/// - **Avoid when**: You need many GenServers (each gets its own OS thread)
59+
/// - **Advantages**: Isolated from main runtime, dedicated thread won't affect other tasks
60+
/// - **Use when**: Long-running singleton services that shouldn't share the main runtime
61+
/// - **Avoid when**: You need many GenServers (each gets its own OS thread + runtime)
62+
/// - **Note**: Still uses async internally (own runtime). For sync code, use `threads::GenServer`
5963
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
6064
pub enum Backend {
6165
/// Run on tokio async runtime (default).
@@ -81,16 +85,19 @@ pub enum Backend {
8185
/// limit of 512 threads. If the pool is exhausted, new blocking tasks wait.
8286
Blocking,
8387

84-
/// Run on a dedicated OS thread.
88+
/// Run on a dedicated OS thread with its own async runtime.
8589
///
8690
/// Use for GenServers that:
87-
/// - Block indefinitely or for long periods
88-
/// - Need guaranteed thread availability
89-
/// - Should not compete with other blocking tasks
90-
/// - Run CPU-intensive workloads
91+
/// - Need isolation from the main tokio runtime
92+
/// - Are long-running singleton services
93+
/// - Should not compete with other tasks for runtime resources
94+
///
95+
/// Each GenServer gets its own thread with a separate tokio runtime,
96+
/// providing isolation from other async tasks. Higher memory overhead
97+
/// (~2MB stack per thread plus runtime overhead).
9198
///
92-
/// Each GenServer gets its own thread, providing complete isolation from
93-
/// the async runtime. Higher memory overhead (~2MB stack per thread).
99+
/// **Note**: This still uses async internally. For fully synchronous code
100+
/// without any async runtime, use [`threads::GenServer`](crate::threads::GenServer).
94101
Thread,
95102
}
96103

@@ -797,7 +804,7 @@ mod tests {
797804
pub fn backend_async_handles_call_and_cast() {
798805
let runtime = rt::Runtime::new().unwrap();
799806
runtime.block_on(async move {
800-
let mut counter = Counter { count: 0 }.start(Backend::Async);
807+
let mut counter = Counter { count: 0 }.start();
801808

802809
// Test call
803810
let result = counter.call(CounterCall::Get).await.unwrap();
@@ -823,7 +830,7 @@ mod tests {
823830
pub fn backend_blocking_handles_call_and_cast() {
824831
let runtime = rt::Runtime::new().unwrap();
825832
runtime.block_on(async move {
826-
let mut counter = Counter { count: 0 }.start(Backend::Blocking);
833+
let mut counter = Counter { count: 0 }.start_with_backend(Backend::Blocking);
827834

828835
// Test call
829836
let result = counter.call(CounterCall::Get).await.unwrap();
@@ -849,7 +856,7 @@ mod tests {
849856
pub fn backend_thread_handles_call_and_cast() {
850857
let runtime = rt::Runtime::new().unwrap();
851858
runtime.block_on(async move {
852-
let mut counter = Counter { count: 0 }.start(Backend::Thread);
859+
let mut counter = Counter { count: 0 }.start_with_backend(Backend::Thread);
853860

854861
// Test call
855862
let result = counter.call(CounterCall::Get).await.unwrap();
@@ -876,9 +883,9 @@ mod tests {
876883
// Similar to badly_behaved_thread but using Backend::Thread
877884
let runtime = rt::Runtime::new().unwrap();
878885
runtime.block_on(async move {
879-
let mut badboy = BadlyBehavedTask.start(Backend::Thread);
886+
let mut badboy = BadlyBehavedTask.start_with_backend(Backend::Thread);
880887
let _ = badboy.cast(Unused).await;
881-
let mut goodboy = WellBehavedTask { count: 0 }.start(ASYNC);
888+
let mut goodboy = WellBehavedTask { count: 0 }.start();
882889
let _ = goodboy.cast(Unused).await;
883890
rt::sleep(Duration::from_secs(1)).await;
884891
let count = goodboy.call(InMessage::GetCount).await.unwrap();
@@ -898,9 +905,9 @@ mod tests {
898905
let runtime = rt::Runtime::new().unwrap();
899906
runtime.block_on(async move {
900907
// Start counters on all three backends
901-
let mut async_counter = Counter { count: 0 }.start(Backend::Async);
902-
let mut blocking_counter = Counter { count: 100 }.start(Backend::Blocking);
903-
let mut thread_counter = Counter { count: 200 }.start(Backend::Thread);
908+
let mut async_counter = Counter { count: 0 }.start();
909+
let mut blocking_counter = Counter { count: 100 }.start_with_backend(Backend::Blocking);
910+
let mut thread_counter = Counter { count: 200 }.start_with_backend(Backend::Thread);
904911

905912
// Increment each
906913
async_counter.call(CounterCall::Increment).await.unwrap();
@@ -928,7 +935,7 @@ mod tests {
928935
let runtime = rt::Runtime::new().unwrap();
929936
runtime.block_on(async move {
930937
// Using Backend::default() should work the same as Backend::Async
931-
let mut counter = Counter { count: 42 }.start(Backend::default());
938+
let mut counter = Counter { count: 42 }.start();
932939

933940
let result = counter.call(CounterCall::Get).await.unwrap();
934941
assert_eq!(result, 42);

0 commit comments

Comments
 (0)