|
| 1 | +# Architecture |
| 2 | + |
| 3 | +zThread uses a layered architecture to isolate the public Java API from the underlying native Linux mechanisms. The framework relies on the Java Foreign Function & Memory (FFM) API to avoid JNI overhead. |
| 4 | + |
| 5 | +## High-level architecture |
| 6 | + |
| 7 | +The system consists of two primary boundaries: |
| 8 | +1. **User Space (Java):** Where the developer registers handlers, posts events, and configures the runtime. |
| 9 | +2. **Kernel Space (Linux):** Where the event loop thread sleeps (`epoll_wait`) until an event occurs on a file descriptor. |
| 10 | + |
| 11 | +```mermaid |
| 12 | +graph TD |
| 13 | + subgraph Java Application |
| 14 | + A[Producer Thread 1] -->|post| Q(MPSC Ring Buffer) |
| 15 | + B[Producer Thread 2] -->|post| Q |
| 16 | + H[Event Handlers] |
| 17 | + end |
| 18 | +
|
| 19 | + subgraph zThread Runtime |
| 20 | + Q -->|eventfd signal| EL(Event Loop Thread) |
| 21 | + EL -->|dispatch| H |
| 22 | + NP(Native Poller) -->|epoll_wait| EL |
| 23 | + end |
| 24 | +
|
| 25 | + subgraph Linux Kernel |
| 26 | + EP[epoll instance] |
| 27 | + EF[eventfd] |
| 28 | + TF[timerfd] |
| 29 | + IF[inotify] |
| 30 | + EF --> EP |
| 31 | + TF --> EP |
| 32 | + IF --> EP |
| 33 | + EP -->|wake| NP |
| 34 | + end |
| 35 | +``` |
| 36 | + |
| 37 | +## Layered architecture |
| 38 | + |
| 39 | +### 1. The Core API (`zthread-core`) |
| 40 | +Provides interface definitions that application developers interact with. It contains no OS-specific logic. |
| 41 | +* `ZRuntime`: The main interface for starting the loop and posting events. |
| 42 | +* `ZRuntimeBuilder`: Fluent builder for configuration. |
| 43 | +* `ZRuntimeFactory`: SPI interface used by the builder to discover the native implementation at runtime. |
| 44 | + |
| 45 | +### 2. The Linux Implementation (`zthread-linux`) |
| 46 | +Implements the core interfaces using native calls. |
| 47 | +* `LinuxRuntime`: The concrete implementation of `ZRuntime`. |
| 48 | +* `LinuxEventLoop`: A dedicated thread that continuously polls for events and drains the MPSC ring buffer. |
| 49 | +* `LinuxNativePoller`: The FFM bridge that links to `libc.so` (or `libc.so.6`). It handles memory segments for `epoll_event` structs and invokes `epoll_create1`, `epoll_ctl`, and `epoll_wait`. |
| 50 | + |
| 51 | +## Request flow |
| 52 | + |
| 53 | +When a producer thread calls `runtime.post(event)`: |
| 54 | + |
| 55 | +1. **Insertion:** The event is written into a lock-free Multi-Producer Single-Consumer (MPSC) Ring Buffer. |
| 56 | +2. **Wakeup Signal:** If the event loop thread is currently parked in the kernel (`epoll_wait`), the producer writes an 8-byte integer to an `eventfd`. |
| 57 | +3. **Kernel Wakeup:** The kernel detects activity on the `eventfd`, wakes the event loop thread, and returns control to `LinuxNativePoller`. |
| 58 | +4. **Drain & Dispatch:** The event loop reads the `eventfd` to clear the signal, then drains the entire MPSC ring buffer, passing each event to its registered handler sequentially. |
| 59 | + |
| 60 | +## Component responsibilities |
| 61 | + |
| 62 | +* **MPSC Ring Buffer:** Handles high-throughput, thread-safe queuing of events from multiple producer threads without locking. |
| 63 | +* **Native Poller:** Manages native off-heap memory allocation for Linux structures and executes exact syscalls via FFM. |
| 64 | +* **Event Dispatcher:** Maintains a map of event types to `Consumer<T>` handlers and executes them when the loop drains the buffer. |
0 commit comments