Documentation Index Fetch the complete documentation index at: https://docs.monolex.ai/llms.txt
Use this file to discover all available pages before exploring further.
Concurrency Patterns: The 5-Pattern Pipeline
Monolex uses a synergistic pipeline of five concurrency patterns to handle high-volume terminal output. Each pattern solves its own problem AND enables the next pattern to work correctly.
The Complete Pipeline
PTY Master (unlimited speed)
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PATTERN 1: Unbounded Channel β
β Guarantee: NO DATA LOSS β
β Mechanism: Unlimited buffer, never drops β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PATTERN 2: Unix Socket Kernel Buffer β
β Guarantee: NATURAL BACKPRESSURE β
β Mechanism: ~208KB kernel buffer, blocks write when full β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PATTERN 3: Actor (SessionActor) β
β Guarantee: NO RACE CONDITIONS, ORDERED PROCESSING β
β Mechanism: Single owner, message queue (MPSC) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PATTERN 4: AtomicState (Coalescing Buffer) β
β Guarantee: FIXED MEMORY, LATEST STATE ONLY β
β Mechanism: Overwrite (not accumulate) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PATTERN 5: ACK Flow Control β
β Guarantee: SCREEN STABILITY β
β Mechanism: Wait for render confirmation before next emit β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
xterm.js WebGL Render (60fps)
Data Reduction Summary
Stage Input Output Reduction 1. Unbounded Channel 10,000/sec 10,000/sec 0% (preserves all) 2. Socket Buffer 10,000/sec 10,000/sec 0% (backpressure only) 3. Actor 10,000/sec 10,000/sec 0% (ordering only) 4. AtomicState 10,000/sec ~500/sec 95% (coalescing) 5. ACK ~500/sec 60/sec 88% (rate limiting) TOTAL 10,000/sec 60/sec 99.4%
All 10,000 updates are PROCESSED by the VTE parser. Only EMISSION to frontend is reduced. This is state coalescing , not data loss.
Pattern 1: Actor over Mutex
SessionActor pattern eliminates lock contention through message-passing concurrency.
The Problem
Multiple sources want terminal state simultaneously:
PTY Output Thread βββββββ
β
User Input Handler ββββββΌβββββββΆ Terminal State βββββββ Resize Handler
β (Grid)
Renderer Timer ββββββββββ β²
β
Close Handler
Without protection: DATA RACE
Why Actor Wins
Mutex Approach
Writers block readers
Lock contention under high PTY output
Priority inversion (resize blocks PTY)
Deadlock risk with multiple resources
Actor Approach
No blocking (async send)
FIFO guaranteed
Impossible deadlock
Easy to reason about
Timeline Comparison
Mutex:
T=0ms PTY: lock() βββΆ write βββΆ unlock()
T=1ms Resize: lock() βββΆ BLOCKED (50ms!)
T=51ms Resize: finally acquires lock
Actor:
T=0ms PTY: tx.send(Line1) βββΆ completes instantly
T=0ms Resize: tx.send(Resize) βββΆ completes instantly
T=0ms Actor: recv(Line1) βββΆ process
T=1ms Actor: recv(Resize) βββΆ apply NEW dimensions
T=2ms Actor: recv(Line2) βββΆ process with NEW dimensions
Pattern Origin : Actor model from Carl Hewitt (1973), proven in Erlang telecom systems (99.9999999% uptime).
Pattern 2: ACK Flow Control
ACK gate blocks updates when waiting for frontend confirmation.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ACK FLOW CONTROL LOGIC β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β BACKEND (Rust) FRONTEND (TypeScript) β
β βββββββββββββββββ βββββββββββββββββββββ β
β β
β pull() called β
β β β
β βΌ β
β βββββββββββββββββββββ β
β β waiting_ack? β β
β βββββββββββ¬ββββββββββ β
β β β
β βββββββ΄ββββββ β
β β β β
β YES NO β
β β β β
β βΌ βΌ β
β ββββββββββ ββββββββββββββββββββββ β
β β return β β build_update() β β
β β None β β waiting_ack = true βββββ emit βββββΆβββββββββββββββ β
β ββββββββββ β start timeout β β inject() β β
β ββββββββββββββββββββββ β β β
β β success? β β
β ββββββββ¬βββββββ β
β β β
β ββββββββββββββββββββββββββββββββββββ β
β β β
β βΌ β
β ββββββββββββββββββββββββββββββββββ β
β β grid_ack() βββΆ waiting_ack=falseβ β
β β ready for next emit β β
β ββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ACK State Machine
ββββββββββββββββββββββββββββββ
β β
ββββββββββββββββββΌβββββββββββββββββ emit() β
β β βββββββββββ
β waiting_ack = false β
β (READY TO EMIT) β
β β
ββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
β new PTY data arrives
β emit("pty-grid")
β waiting_ack = true
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β waiting_ack = true β βββ More PTY data arrives
β (WAITING FOR ACK) β AtomicState absorbs, no emit
β β
ββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β Frontend: invoke("grid_ack")
β waiting_ack = false
β
βββββΆ back to READY TO EMIT
Timeline Example
T=0ms PTY data arrives, waiting_ack=false βββΆ emit("pty-grid"), waiting_ack=true
T=5ms PTY data arrives, waiting_ack=true βββΆ AtomicState absorbs (NO emit)
T=10ms PTY data arrives, waiting_ack=true βββΆ AtomicState absorbs (NO emit)
T=15ms PTY data arrives, waiting_ack=true βββΆ AtomicState absorbs (NO emit)
T=16ms Frontend renders, invoke("grid_ack") βββΆ waiting_ack=false
T=16ms New state ready βββΆ emit("pty-grid"), waiting_ack=true
...
Result: 4 PTY updates, 2 emits, 0 frame drops, smooth 60fps
Pattern 3: EPOCH Sync (Resize Safety)
Epoch validation prevents stale GridUpdates after resize.
The Resize Problem
T=0ms GridUpdate (epoch=1, 80x24) in flight
T=1ms User resizes terminal to 120x40
T=2ms Frontend receives old GridUpdate (80x24)
βββΆ WRONG DIMENSIONS! Corruption!
EPOCH Solution
T=0ms GridUpdate (epoch=1, 80x24) in flight
T=1ms User resizes: prepareResize() βββΆ epoch=2
T=2ms Frontend receives old GridUpdate (epoch=1)
T=2ms epoch=1 < currentEpoch=2 βββΆ REJECTED (no corruption)
T=3ms New GridUpdate (epoch=2, 120x40) arrives βββΆ APPLIED
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β EPOCH SYNCHRONIZATION FLOW β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β USER ACTION FRONTEND BACKEND β
β βββββββββββ ββββββββ βββββββ β
β β
β Resize window β
β β β
β βΌ β
β βββββββββββββββββββββ β
β β prepareResize() β β
β β currentEpoch++ βββββββ send epoch βββββββΆ ββββββββββββββββββββ
β β (e.g., 1 β 2) β β resize(epoch=2) ββ
β βββββββββββββββββββββ β store new epoch ββ
β ββββββββββββββββββββ
β β
β Later: Old update arrives (epoch=1) β
β Frontend checks: 1 < 2? β REJECT β
β β
β Later: New update arrives (epoch=2) β
β Frontend checks: 2 >= 2? β ACCEPT β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Pattern 4: AtomicState Absorber
AtomicState overwrites instead of queuing, guaranteeing fixed memory.
Overwrite vs Queue
Queue Approach (BAD) Input: S1 βββΆ S2 βββΆ S3 βββΆ ... βββΆ S10
Queue: [S1][S2][S3]...[S10]
Memory: Grows indefinitely
User: Sees OLD states
Overwrite Approach (GOOD) Input: S1 βββΆ S2 βββΆ S3 βββΆ ... βββΆ S10
State: [S10] (only current)
Memory: Fixed (~80KB)
User: Sees CURRENT state
Memory Calculation
Typical Terminal: 120 cols x 40 rows = 4,800 cells
Cell Size:
- char: 4 bytes (UTF-32)
- fg: 4 bytes (RGBA)
- bg: 4 bytes (RGBA)
- flags: 4 bytes
- width: 1 byte
Total: ~17 bytes/cell
Grid Memory: 4,800 x 17 = 81,600 bytes = ~80KB
With scrollback (1000 lines):
(40 + 1000) x 120 x 17 = ~2MB
Memory Comparison (1 minute of high output)
Approach Calculation Memory Queue-Based 1000 states/sec x 60 sec x 80KB 4.8GB AtomicState 1 state x 80KB 80KB Difference - 60,000x less
The Dual Guarantee
ONE mechanism (overwrite) provides TWO guarantees:
1. MEMORY STABILITY
Queue: [S1][S2][S3]...[S1000] βββΆ Memory grows
Overwrite: [S1000] βββΆ Memory fixed
2. TEMPORAL CONSISTENCY
Queue: User sees S1, S2, S3... (past states)
Overwrite: User sees S1000 (current state)
For terminals, CURRENT is what matters. Intermediate states are noise.
Pattern 5: BSU/ESU Detection
Synchronized Update detection prevents mid-frame rendering.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BSU/ESU DETECTION β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β DECSET Mode 2026 markers: β
β β
β BSU (Begin Synchronized Update): β
β β’ DCS format: ESC P = 1 s ESC \ β
β β’ DEC mode: ESC [ ? 2026 h β
β β
β ESU (End Synchronized Update): β
β β’ DCS format: ESC P = 2 s ESC \ β
β β’ DEC mode: ESC [ ? 2026 l β
β β
β Detection: Scan incoming bytes for these patterns β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
How It Works
Shell sends: BSU + [frame data] + ESU
T=0ms BSU detected βββΆ syncing=true, sync_deadline=16ms
T=1ms frame data arrives βββΆ AtomicState absorbs (no pull allowed)
T=5ms frame data arrives βββΆ AtomicState absorbs
T=10ms ESU detected βββΆ syncing=false
T=10ms pull() called βββΆ returns GridUpdate with complete frame
Result: User sees complete frame, no partial renders
Timeout Safety
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TIMEOUT SAFETY (16ms) β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β BSU detected β
β β β
β βΌ β
β ββββββββββββββββββββββββββββββ β
β β syncing = true β β
β β deadline = now + 16ms β β
β βββββββββββββββ¬βββββββββββββββ β
β β β
β βββββββββββ΄ββββββββββ β
β β β β
β ESU arrives Timeout (16ms) β
β β β β
β βΌ βΌ β
β βββββββββββββββ βββββββββββββββ β
β βsyncing=falseβ βsyncing=falseβ β Prevents deadlock β
β β (normal) β β (timeout) β β
β βββββββββββββββ βββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
If ESU never arrives, timeout releases the gate after 16ms to prevent deadlock.
Synergy Matrix
Each pattern solves its own problem AND helps others:
Pattern Own Guarantee Helps Next Pattern 1. Unbounded Channel No data loss All downstream patterns receive complete data 2. Socket Buffer Natural backpressure (~208KB limit) Unbounded channel doesnβt grow infinitely 3. Actor No race conditions, ordered processing AtomicState receives ordered updates 4. AtomicState (Coalesce) Fixed memory, latest state only ACK doesnβt need to handle thousands of updates 5. ACK Screen stability, 60fps guarantee Frontend renders smoothly at sustainable rate
Reverse Dependency (Efficiency Cascade)
ACK slows emit rate (60/sec max)
β
ββββΆ AtomicState absorbs more updates per emit
β
ββββΆ Data reduction ratio increases
β
ββββΆ Better efficiency, less work per emit
AtomicState processes instantly (just overwrite)
β
ββββΆ Actor's message queue stays short
β
ββββΆ No command backlog
β
ββββΆ Actor loop runs fast
Actor reads socket continuously (no blocking)
β
ββββΆ Socket buffer drains quickly
β
ββββΆ write() rarely blocks
β
ββββΆ PTY Daemon stays fast
What If You Remove a Pattern?
Without Pattern 1 (Unbounded Channel)
Bounded channel would drop data when full
Terminal output corrupted, missing content
User sees incomplete results
Without Pattern 2 (Socket Buffer)
No kernel-level backpressure
Pattern 1βs unbounded channel could grow infinitely
Memory explosion if Tauri is slow
Without Pattern 3 (Actor)
Multiple threads accessing state simultaneously
Race conditions, data corruption
Locks required -> contention -> slowdown
Without Pattern 4 (AtomicState)
Need queue between Actor and ACK
Queue grows: 10,000 - 60 = 9,940 items/sec accumulation
Memory grows indefinitely
Temporal mismatch: user sees past, not present
Frontend receives all ~500 coalesced states/sec
xterm.js event queue grows
Frame drops, stuttering
Screen instability
Pattern Origins
These are NOT new inventions. They are PROVEN patterns combined for terminal rendering:
Pattern Origin Proven In Unbounded Channel Rust std library (mpsc) Async systems, message passing Socket Buffer Unix (1983), BSD Sockets 40+ years of network programming Actor Carl Hewitt (1973), Erlang (1986) Erlang telecom (99.9999999% uptime) Coalescing Buffer GUI frameworks (decades old) React batching, game engines ACK Flow Control TCP/IP (1974), Vint Cerf Every internet connection, 50+ years
Monolexβs innovation: Putting these patterns together in the RIGHT LAYER (VTE parsing layer, not IPC layer).
SMPC/OFAC Applied
SMPC (Simplicity is Managed Part Chaos) :
Each pattern is SIMPLE (one purpose, one guarantee)
Combined, they handle COMPLEX scenarios (high output, concurrent access)
No single βcomplexβ solution - 5 simple solutions working together
OFAC (Order is a Feature of Accepted Chaos) :
Accept: PTY output is chaotic (unlimited, unpredictable)
Accept: Renderer is slow (60fps max)
Accept: Intermediate states donβt matter
Order emerges: User sees current state, screen is stable
The architecture doesnβt FIGHT chaos. It ACCEPTS chaos and extracts ORDER.