Workers
Purpose
Workers shares CPU execution capacity between workload groups. Groups define admission, concurrency, relative scheduling share and optional CPU/locality policy without creating another physical pool per workload.
Interface
Types below are in CE::Workers unless another namespace is shown.
Types and operations
API and purpose |
|---|
|
|
|
|
|
CPU policy enums
Type |
Choices and details |
|---|---|
Explicit eligible CPU IDs, strength, locality and optional cache-domain selection. CPU policy and capabilities. |
|
|
|
|
|
|
Usage
For a running game, create a tracked group through
engine.make_worker_group(options). Submit CPU-only work with owned inputs and
retain its future. Runtime settles these groups during shutdown while accepted
platform dependencies can still progress.
---
config:
theme: base
themeVariables:
fontFamily: system-ui, sans-serif
fontSize: 14px
flowchart:
htmlLabels: true
curve: linear
nodeSpacing: 22
rankSpacing: 38
padding: 12
---
flowchart LR
accTitle: Workers · simple Context-owned groups
accDescr: Local names omit Workers::; ambiguous nested namespaces remain qualified. Arrows point toward dependencies. Application roles are rounded; named API operations have rounded corners. Dashed arrows mark optional choices.
k0(["Application<br/>composition"]):::app
k1["Runtime::<br/>ExecutionOptions"]:::neighbor
k2["Runtime::<br/>Context"]:::neighbor
k3["Pool"]:::focal
k4["Group"]:::focal
k5(["Application<br/>CPU preparation"]):::app
k6["GroupOptions"]:::focal
k0 --> k1
k2 --> k1
k2 --> k3
k2 --> k4
k5 --> k4
k4 --> k6
classDef focal fill:#e7f3ef,stroke:#387d6b,color:#153d33,stroke-width:1.2px
classDef neighbor fill:#f0f3f8,stroke:#8c9bb1,color:#35445b,stroke-width:1px
classDef app fill:#fff2df,stroke:#c09452,color:#674515,stroke-dasharray:5 3
classDef system fill:#eaf0fc,stroke:#617fab,color:#263f69,stroke-width:1.2px
linkStyle default stroke:#7e8fa7,stroke-width:1.2px
Local names omit Workers:: where unambiguous. Explore this diagram and its other views →
Explore application preparation, a pool shared by contexts, or worker implementation dependencies.
Choose pool and group ownership
Situation |
Construction path |
Who closes and drains it? |
|---|---|---|
One game’s ordinary CPU preparation |
Set |
Runtime/Context tracks every resulting group. Owned physical capacity is created lazily; the default is one worker. |
Several contexts or services share physical capacity |
Supply |
Each context closes/drains its groups; the application owns the pool and unrelated groups. |
A service runs independently of Runtime |
Own |
The service stops producers, closes acceptance and services dependencies before drain/join. |
CPU/cache policy needs native topology |
Set |
The pool retains the provider through worker joins. The optional Workers module supplies hwloc discovery. |
Separate capacity from scheduling policy
Setting |
Effect |
Decision to make |
|---|---|---|
Pool worker count |
Physical CPU threads shared by all groups |
Choose total capacity once. Context’s owned count must be positive; standalone |
Running-job cap, limited to pool capacity; zero uses that capacity |
Limit a workload without allocating extra threads. |
|
|
Relative selection share among eligible groups |
Balance queued work; neither setting guarantees latency, completion order or OS priority. |
Eligible CPUs and optional locality/cache policy |
Choose Required rejection or Preferred fallback, then inspect effective policy/capabilities. |
A job’s future carries its result or failure. A closed group’s drain() also
waits for accepted jobs and capture release; status counters alone are not that
barrier. The worker contract defines
scheduling and policy limits.
Uses
Dependency |
Workers’ use |
|---|---|
Optional startup discovery and supported CPU policy application; the neutral pool does not implicitly load a provider. |
|
Validate requested eligibility/locality against pool capabilities and verify required native policy before callback entry. |
|
Diagnostics and Logging |
Identify groups/pools and expose queue, callback and policy observations. |
Graphics follow-up belongs to the application’s job workflow through Dispatch. The pool itself supplies CPU execution and has no owner-dispatch dependency.
Used by
Consumer |
Relationship to the pool |
|---|---|
Create tracked groups on lazy owned or supplied shared capacity. Context ownership. |
|
Execute one serial listener stream over a group; separate adapters can run concurrently. Event delivery. |
|
Create a Context-tracked serial preparation group, submit owned text requests, then upload through platform dispatch. Text updates. |
|
Schedule independent CPU operations and retain their results; these services do not automatically submit preparation jobs. |
|
Standalone application service |
Share physical capacity without constructing a game session. |
Contracts
Jobs own callables and settle futures with results/errors. FIFO selection does not imply completion order when concurrency exceeds one. Caps limit running jobs; weight/priority determine selection share rather than OS scheduling priority. CPU eligibility is not reserved core ownership or guaranteed speedup.
Do not block a job on child futures from the same saturated pool. Close before drain; drainage waits for accepted work and capture release. Same-pool drainage and self-join reject. Required unsupported native policy rejects while preferred policy may report fallback.
Lifecycle
Create a pool and groups, submit owned work, close acceptance and drain before destroying borrowed dependencies. Pool destruction closes, drains and joins; saved group handles reject safely after pool disappearance. Thread-start failure joins threads already created. Context-created groups close with that context; unrelated groups in an injected shared pool remain open.
Execution
Physical workers execute eligible groups according to scheduling policy. They are separate from runtime’s dedicated concurrent simulation thread. Graphics work still needs platform dispatch. During runtime shutdown, accepted CPU work settles while platform dependencies can continue making progress.
Integration
Before context creation, select the desired physical capacity through
ExecutionOptions; its default
is one worker. During game initialization, retain a context-owned preparation group:
auto preparation = engine_.make_worker_group({.max_concurrency = 2});
auto result = preparation.submit([] { return 6 * 7; });
Real preparation should return owned CPU data. Retain/read its future and send completed results to platform for upload; the group’s cap cannot exceed physical pool capacity and does not create two additional threads. To permit two jobs to run at once, the configured pool must contain at least two workers.
Limits and further reading
No work stealing, forced termination, live pool reconfiguration or NUMA memory placement is implied. Topology discovery does not prove a performance benefit. Read worker contracts and optional integration, runtime shutdown and pool/group declarations.