Acme-Parataxis
view release on metacpan or search on metacpan
## [v0.0.10] - 2026-02-22
This version comes with a dynamic thread pool and an improved API.
### Added
- New ergonomic API using exported functions like `async { ... }`, `fiber { ... }`, and `await( $target )`.
### Changed
- Refactored native thread pool to use cond vars (`PARA_COND_*`) instead of busy polling, reducing idle CPU usage to near zero.
- Switched to a global job queue for the thread pool for better load balancing across worker threads.
- Reduced default fiber stack size from 4MB to 512K.
- Worker threads are now only spawned when the first asynchronous job is submitted.
- Increased `MAX_FIBERS` limit to 1024.
- Expose thread pool config with `set_max_threads` and `max_threads`.
## [v0.0.9] - 2026-02-21
Asynchronous HTTP::Tiny is basically a semi-automatic footgun.
### Fixed
## Architectural Inspiration
The concurrency model in Parataxis is heavily inspired by the **Wren** programming language, specifically its treatment
of fibers as the primary unit of execution and its deterministic cooperative scheduling.
## Stack Virtualization
On Unix-like systems, we use `ucontext.h` to manage stack and register state. On Windows, we leverage the native
`Fiber API`. In both cases, we perform heart surgery on the Perl interpreter by manually teleporting its internal
global pointers (the `PL_*` variables) between contexts.
## Shared CVs and Pad Virtualization
A significant challenge in Perl green threads is the shared nature of PadLists and the global `CvDEPTH` counter. In
debug builds of Perl, calling a shared subroutine from multiple fibers can trigger internal assertions (like
`AvFILLp(av) == -1`). Parataxis includes a specialized workaround that surgically cleans the next landing pad before
every context switch to satisfy these assertions without clobbering active lexical state.
## `eval` vs. `try/catch`
While `feature 'try'` is available in modern Perl, manually teleporting interpreter state can occasionally confuse the
compiler's expectations for stack unwinding. Standard `eval { ... }` remains the most predictable way to handle
exceptions within fibers.
lib/Acme/Parataxis.c view on Meta::CPAN
* OS threads without stalling the main interpreter.
*
* @section Architecture
* - **Fibers**: The primitive unit of execution. Each fiber has its own OS context
* and a complete set of Perl interpreter stacks (Argument, Mark, Scope, Save, Mortal).
* - **Coroutines**: The execution pattern (yield/call/transfer) used by fibers to
* pass control.
* - **Thread Pool**: A fixed pool of worker threads that poll a job queue for
* blocking operations like sleep, I/O, or heavy computation.
* - **Context Switching**: The `swap_perl_state` function manually saves and restores
* the global state of the Perl interpreter (`PL_*` variables) to allow disjoint
* execution flows.
*
* @section Caveats
* Shared subroutines (CVs) with re-entrant yielding calls are handled by a
* specialized pad-clearing mechanism in `_activate_current_depths` to satisfy
* Perl's internal `AvFILLp` assertions in debug builds.
*/
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
lib/Acme/Parataxis.c view on Meta::CPAN
JMPENV * top_env; /**< Pointer to the top exception environment (eval/die buffers) */
COP * curcop; /**< Current Op Pointer (location in the source/bytecode) */
OP * op; /**< Current Operation being executed */
PAD * comppad; /**< Current lexical Pad (variable storage) */
SV ** curpad; /**< Array pointer to the current lexical Pad */
PMOP * curpm; /**< Current pattern match state */
PMOP * curpm_under; /**< Current pattern match state under */
PMOP * reg_curpm; /**< Current regex match state */
GV * defgv; /**< The $_ global */
GV * last_in_gv; /**< GV used in last <FH> */
SV * rs; /**< The $/ global */
GV * ofsgv; /**< The $, global */
SV * ors_sv; /**< The $\ global */
GV * defoutgv; /**< The default output filehandle */
HV * curstash; /**< Current package stash */
HV * defstash; /**< Default package stash */
SV * errors; /**< Outstanding queued errors */
SV * user_cv; /**< The Perl sub/coderef this fiber is running */
SV * self_ref; /**< The Acme::Parataxis Perl object wrapper */
SV * transfer_data; /**< Arguments or return values passed during yield/transfer */
lib/Acme/Parataxis.c view on Meta::CPAN
}
}
}
}
}
/**
* @brief Swaps the internal Perl Interpreter state pointers.
*
* This is the core of the fiber implementation. It manually saves all
* global pointers that define the "state" of the Perl virtual machine for
* the current context and restores them for the target context.
*
* @param from Context being paused.
* @param to Context being resumed.
*/
void swap_perl_state(para_fiber_t * from, para_fiber_t * to) {
dTHX;
/* Save current state into 'from' context */
from->si = PL_curstackinfo;
lib/Acme/Parataxis.c view on Meta::CPAN
Newx(c->savestack, sz, ANY);
c->savestack_ix = 0;
c->savestack_max = sz;
Newx(c->tmps_stack, sz, SV *);
c->tmps_ix = -1;
c->tmps_floor = -1;
c->tmps_max = sz;
// Inherit initial globals from current interpreter state
c->curcop = PL_curcop;
c->op = PL_op;
c->top_env = PL_top_env;
c->curpm = PL_curpm;
c->curpm_under = PL_curpm_under;
c->reg_curpm = NULL;
c->defgv = PL_defgv;
c->last_in_gv = PL_last_in_gv;
c->rs = PL_rs;
c->ofsgv = PL_ofsgv;
lib/Acme/Parataxis.c view on Meta::CPAN
}
Safefree(c->tmps_stack);
}
free(c);
}
/**
* @brief Global cleanup function for the fiber and thread pool system.
*
* Signals all worker threads to terminate and destroys all remaining
* fibers. Should be called during global destruction or system shutdown.
*/
DLLEXPORT void cleanup() {
dTHX;
if (threads_initialized) {
LOCK(queue_lock);
threads_keep_running = 0;
PARA_COND_BROADCAST(queue_cond);
UNLOCK(queue_lock);
#ifdef _WIN32
lib/Acme/Parataxis.pod view on Meta::CPAN
=head2 Architectural Inspiration
The concurrency model in Parataxis is heavily inspired by the B<Wren> programming language, specifically its treatment
of fibers as the primary unit of execution and its deterministic cooperative scheduling.
=head2 Stack Virtualization
On Unix-like systems, we use C<ucontext.h> to manage stack and register state. On Windows, we leverage the native
C<Fiber API>. In both cases, we perform heart surgery on the Perl interpreter by manually teleporting its internal
global pointers (the C<PL_*> variables) between contexts.
=head2 Shared CVs and Pad Virtualization
A significant challenge in Perl green threads is the shared nature of PadLists and the global C<CvDEPTH> counter. In
debug builds of Perl, calling a shared subroutine from multiple fibers can trigger internal assertions (like
C<AvFILLp(av) == -1>). Parataxis includes a specialized workaround that surgically cleans the next landing pad before
every context switch to satisfy these assertions without clobbering active lexical state.
=head2 C<eval> vs. C<try/catch>
While C<feature 'try'> is available in modern Perl, manually teleporting interpreter state can occasionally confuse the
compiler's expectations for stack unwinding. Standard C<eval { ... }> remains the most predictable way to handle
exceptions within fibers.
( run in 1.505 second using v1.01-cache-2.11-cpan-e1769b4cff6 )