Structural Actor Concurrency
Relevant source files
The following files were used as context for generating this wiki page:
Structural Actor Concurrency is a core design pillar of the Sploosh programming language, combining Elixir-style actor models with Rust-level memory safety. The system is designed to provide isolated concurrent execution units that communicate via message passing, effectively eliminating shared mutable state and the associated class of concurrency bugs, such as data races.
The architecture enforces strict isolation: every actor manages its own private state, and the only way to interact with an actor or its state is through a Handle<T>. This handle allows for two types of communication: asynchronous fire-and-forget messages and synchronous request/reply interactions.
Sources: README.md:20-30, VISION.md:40-45, VISION.md:75-80
Architecture and Components
Actor Definition
An Actor in Sploosh is an isolated unit of execution containing private state and a message mailbox. It is defined using the actor keyword and contains fields for state and functions designated as handlers for incoming messages.
Sources: crates/sploosh-ast/src/lib.rs:135-140, crates/sploosh-parser/src/lib.rs:252-288
This diagram illustrates the internal structure of an Actor as represented in the Abstract Syntax Tree (AST).
Sources: crates/sploosh-ast/src/lib.rs:135-152
Handle and Lifecycle
Actors are instantiated using the spawn keyword, which returns a Handle<T>. A Handle is a reference-counted, cloneable, and thread-safe (Clone + Send) reference to a running actor. Communication is strictly routed through these handles.
Sources: README.md:28, VISION.md:86-88
| Component | Keyword/Type | Description |
|---|---|---|
| Actor Declaration | actor | Defines the state and message handlers. |
| Instantiation | spawn | Starts a new actor instance and returns a Handle. |
| Reference | Handle<T> | A Clone + Send reference to a running actor. |
| Messaging | send | Statement used to dispatch asynchronous fire-and-forget messages. |
| State | state | Private data internal to the actor instance. |
| Sources: README.md:20-35, VISION.md:84-90 |
Communication Patterns
Messaging Flow
Sploosh distinguishes between asynchronous and synchronous communication based on the use of the send keyword:
- Asynchronous (
send): Dispatching a message using thesendkeyword is a fire-and-forget operation. The caller does not wait for a response. - Synchronous (Direct Call): Calling a public method on a
Handle<T>without thesendkeyword results in a request/reply pattern that blocks the caller until the actor returns a value.
The sequence diagram demonstrates the lifecycle from spawning to different communication modes.
Sources: README.md:27-33, crates/sploosh-parser/src/lib.rs:604-620
Structural Restrictions
The compiler and parser enforce specific rules to maintain the integrity of the actor model:
- Method Call Requirement: The operand of a
sendstatement must be a method call on a handle (e.g.,handle.method()). - Isolation: Actors are the only way to express mutable shared state. Shared immutable data is handled via the
Shared<T>primitive. - Prohibitions: Actor systems are prohibited in
onchain modblocks, which are restricted to deterministic blockchain execution.
Sources: crates/sploosh-parser/src/lib.rs:612-620, VISION.md:89-91, VISION.md:83-85
Implementation Details
The Sploosh parser implements specific logic for handling actor-related syntax. The send keyword is treated as a statement-head rule; it only opens a send-statement if the next token can begin an expression.
// From crates/sploosh-parser/src/lib.rs:604-620
} else if self.at_ident_text("send") && self.peek_kind_at(1).is_some_and(can_begin_expr)
{
self.bump();
let expr = self.expr(0)?;
if !is_method_call(&expr) {
self.error_at(
expr.span,
"`send` operand must be a method call on a handle",
);
}
self.expect(TokenKind::Semi)?;
statements.push(Stmt::Expr(expr));
}
Sources: crates/sploosh-parser/src/lib.rs:604-620
Supervised Actors
Sploosh follows an Elixir-style supervision model. Actors are supervised, allowing for fault-tolerant hierarchies. This is supported by attributes like @supervisor, which can configure restart strategies (e.g., "one_for_one").
Sources: VISION.md:44-46, crates/sploosh-parser/src/lib.rs:1130-1140
Summary
Structural Actor Concurrency in Sploosh provides a robust framework for building concurrent systems by enforcing isolation and formalizing communication patterns. By integrating these patterns directly into the language syntax and AST (as seen in ItemKind::Actor and Stmt::Expr via send), Sploosh ensures that LLMs and developers alike follow a single, safe path for managing concurrency without the risks of shared mutable state.
Sources: README.md:75-80, VISION.md:120-125