10 releases
| 0.5.1 | Dec 31, 2025 |
|---|---|
| 0.5.0 | Jul 10, 2024 |
| 0.4.4 | Jun 25, 2024 |
| 0.4.0 | May 19, 2024 |
| 0.1.0 | Feb 10, 2024 |
#716 in Asynchronous
Used in 5 crates
50KB
917 lines
Tokio GenServer
A simple Elixir/Erlang-GenServer-like actor implementation on Tokio.
Please see the documentation for information on usage and examples.
- Simple: Define 3 messages types and at least one callback, and you have an actor. No macro magic. No global "system"s or "pollution".
- Powerful: Initialization and exit callbacks. On completion, returns the actor itself, the whole running environment, and run result.
- Lightweight: Little code. No boxing except the ones introduced by Tokio.
- Blocking aCTOR (
Bctor) for use with synchronous code.
NB: What is a GenServer? A Generic Server is a persistent process that handles messages sent to it. That's it. The message can either be a cast (fire-and-forget) or a call (request-response).
Major difference from Erlang
- Do not panic (crash). Return
anyhow::Errorinstead. - Tokio scheduling is cooperative, not preemptive.
Your long-running async code should call
yield_nowin the middle so they can be interrupted. - Blanket supervision implementations are not very useful.
Instead, let your actors spawn children actors,
and let children send messages to their parents using
before_exitto handle children exiting.
Alternatives
- 👍 Implements "proper" "process"; interfaces closer to Erlang.
- 👍 Type-erasure on "child", "pid".
- 👍 Supervisors.
- 👍 Multi-node.
- ❓ Catches unwind (also bad because of overhead?).
- ❓ Uses flume channels: may be faster, but more dependencies.
- 👎 Requires creating "applications" and "pollutes" the codebase.
- 👎 Call, cast, and reply message types are not distinguished.
- 👎 Uses magic global variables to manage "processes".
- 👎 No blocking.
- 👎 Requires messages to be serializable.
- 👎 Most traits are not object-safe.
Dependencies
~2.3–3.5MB
~54K SLoC