110 lines
4.1 KiB
Markdown
110 lines
4.1 KiB
Markdown
# Thespian
|
|
|
|
Fast & flexible actors for Zig, C & C++ applications
|
|
|
|
To build:
|
|
|
|
```
|
|
zig build
|
|
```
|
|
|
|
See `tests/*` for many interesting examples.
|
|
|
|
To run the tests:
|
|
```
|
|
zig build test
|
|
```
|
|
|
|
---
|
|
|
|
## Architecture Overview
|
|
|
|
Thespian is an actor framework where concurrent units ("instances")
|
|
communicate exclusively via message passing, with no shared mutable state.
|
|
Messages are encoded using **CBOR** (Concise Binary Object Representation).
|
|
|
|
The library has three layers:
|
|
|
|
1. **C++ core** - the primary implementation (`src/instance.cpp`, `src/executor_asio.cpp`, `src/hub.cpp`)
|
|
2. **C API** - a thin wrapper layer in `src/c/` exposing the C++ core to other languages
|
|
3. **Zig module** - `src/thespian.zig` wraps the C API into idiomatic Zig types with comptime features
|
|
|
|
---
|
|
|
|
## Key Concepts
|
|
|
|
**`context`** - the runtime environment. You create one, spawn actors into
|
|
it, then call `run()`. It owns the executor thread pool.
|
|
|
|
**`instance` / actor** - each spawned actor is a `behaviour` (a
|
|
`std::function<result()>`) that registers a `receiver` to handle incoming
|
|
messages. Actors run on an executor. Currently the only executor provided
|
|
in this repo is one backed by ASIO.
|
|
|
|
**`handle` / `pid`** - a reference to a live actor. In C++ this is
|
|
`thespian::handle`; in Zig it is `pid` (owned) or `pid_ref` (borrowed).
|
|
Sending to an expired handle is safe and fails gracefully.
|
|
|
|
**`message`** - a CBOR-encoded byte buffer. Pattern matching uses
|
|
`extract`/`match` with a composable matcher DSL (`string`, `array`, `any`,
|
|
`more`, etc.).
|
|
|
|
**`hub`** - a pub/sub broadcast actor. Subscribers receive all broadcasts;
|
|
supports filtering and Unix socket-based IPC.
|
|
|
|
---
|
|
|
|
## I/O Primitives
|
|
|
|
| Primitive | Purpose |
|
|
| -------------------------------- | ------------------------------------------------ |
|
|
| `timeout` | One-shot timer |
|
|
| `metronome` | Repeating timer |
|
|
| `signal` | OS signal handling |
|
|
| `tcp_acceptor` / `tcp_connector` | TCP networking |
|
|
| `unx_acceptor` / `unx_connector` | Unix domain sockets |
|
|
| `socket` | Raw FD-backed socket I/O |
|
|
| `file_descriptor` | Async wait on arbitrary file descriptors (posix) |
|
|
| `file_stream` | Async read/write on file handles (win32) |
|
|
| `subprocess` | Child process management (platform-specific) |
|
|
|
|
### ⚠️ I/O Primitive Ownership - Critical Rule
|
|
|
|
**Every I/O primitive is owned by the actor that was executing at the time
|
|
it was created.** Async completion messages from a primitive are delivered
|
|
only to that owning actor. There is no way to transfer ownership or
|
|
redirect delivery to a different actor after construction.
|
|
|
|
A common mistake is to create an I/O primitive in one actor and then spawn
|
|
a separate "handler" actor, passing the primitive (or its handle) to it.
|
|
The handler will never receive any events - they will continue to be
|
|
delivered to the original actor that created the primitive.
|
|
|
|
**The correct pattern:** the actor responsible for handling a primitive's
|
|
events must be the one that creates it. If you need a dedicated handler
|
|
actor, have it create its own primitives from within its own behaviour.
|
|
|
|
---
|
|
|
|
## Ownership & Lifecycle
|
|
|
|
- Zig's `pid` is `Owned` (must call `deinit()`); `pid_ref` is `Wrapped`
|
|
(borrowed, no deinit required)
|
|
- Actors can `trap()` exit signals and `link()` to other actors for supervision
|
|
- `spawn_link` ties an actor's lifetime to its parent
|
|
|
|
---
|
|
|
|
## Build System
|
|
|
|
- **Zig 0.15.2+** required
|
|
- Dependencies: `cbor` (CBOR codec), `asio` (ASIO network executor),
|
|
`tracy` (optional profiling via `-Denable_tracy=true`)
|
|
- Produces a static library `libthespian` and a Zig module
|
|
- Tests live in `test/` and cover both the C++ and Zig APIs
|
|
|
|
---
|
|
|
|
## Misc
|
|
|
|
See DeepWiki for more documentation: [](https://deepwiki.com/neurocyte/thespian)
|