You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
1. Set thread-local worker context
2. Initialize backoff with pool config
3. Loop until shutdown:
a. Try recv() (local pop -> global dequeue -> steal)
b. If task: execute, reset backoff
c. If no task: backoff.snooze()
4. Clear thread-local context
6.2 Binary Fork-Join
join(left_fn, right_fn):
1. Create JoinHandle for right result
2. Create context struct with handle + args
3. Spawn right task to pool
4. Execute left task locally (no scheduling overhead)
5. Steal-while-wait for right completion:
a. Check completed flag (acquire)
b. If not done: tryProcessOneTask(), backoff
6. Return (left_result, right_result)
6.3 Structured Concurrency
scope(body_fn):
1. Create Scope with sharded arenas
2. Set as current scope (thread-local)
3. Execute body (body spawns tasks via scope.spawn())
4. Wait for all tasks (pending.load == 0):
a. Steal-while-wait to help
5. Check panic_payload, propagate if set
6. Free all arena allocations
6.4 Parallel Iteration
par_iter().for_each():
1. Calculate chunk size based on:
- Data length
- Thread count
- Splitter config (min_chunk, mode)
2. If shouldSplit() is false: run sequentially
3. Create scope
4. For each chunk: spawn task to process chunk
5. Wait for scope completion
7. Flow Diagrams
7.1 Thread Pool Architecture
+---------------------------------------+
| Global MPMC Queue |
| (overflow + external thread access) |
+------------------+--------------------+
|
+------------------------------+------------------------------+
| | |
v v v
+---------------+ +---------------+ +---------------+
| Worker 0 | | Worker 1 | | Worker N |
| +-----------+ | | +-----------+ | | +-----------+ |
| |Local Deque| | <--steal--> | |Local Deque| | <--steal--> | |Local Deque| |
| |(push/pop) | | | |(push/pop) | | | |(push/pop) | |
| +-----------+ | | +-----------+ | | +-----------+ |
| | | | | |
| Run Loop: | | Run Loop: | | Run Loop: |
| 1. local pop | | 1. local pop | | 1. local pop |
| 2. global | | 2. global | | 2. global |
| 3. steal | | 3. steal | | 3. steal |
| 4. execute | | 4. execute | | 4. execute |
+---------------+ +---------------+ +---------------+
7.2 Fork-Join Execution
join(taskA, taskB)
|
+----------------------+
| |
v v
+-------------+ +-------------+
| Left Task | | Right Task |
| (local) | | (spawned) |
| | | |
| No overhead | | -> Pool -> |
| Just call | | Worker pick |
+------+------+ +------+------+
| |
| steal-while-wait |
|<---------------------+
|
v
+-------------+
| Results |
| (left,right)|
+-------------+
// Create custom poolconstpool=tryThreadPool.init(allocator, .{
.num_threads=4,
.backoff_mode=.balanced,
});
deferpool.deinit();
// Use with join/scopeloom.joinOnPool(pool, taskA, .{}, taskB, .{});
loom.scopeOnPool(pool, body);
// Use with parallel iteratorloom.par_iter(data).withPool(pool).for_each(process);
9.3 Parallel Iterator Methods
par_iter(slice)
.withMinChunk(1000) // Sequential threshold
.withMaxChunks(8) // Cap parallelism
.withPool(custom_pool) // Use specific pool
.withAlloc(allocator) // For filter/map// Terminal operations:
.for_each(fn) // Apply to each element
.reduce(Reducer) // Combine all elements
.map(fn, allocator) // Transform elements
.filter(pred, allocator) // Select elements
.find(pred) // First match
.all(pred) // All match?
.any(pred) // Any match?
10. Context API
The Context API enables passing shared state to parallel operations.
Use pointers to stack-allocated or heap-allocated data
// Good - context lives on stack, outlives par_iterconstctx=Context{ .threshold=100.0 };
par_iter(data).withContext(&ctx).forEach(fn);
// Bad - temporary contextpar_iter(data).withContext(&Context{ ... }).forEach(fn); // May not work
Thread Safety:
Context is shared across ALL worker threads
Read-only fields: no synchronization needed
Mutable counters: use std.atomic.Value(T)
Complex mutations: use mutexes
Best performance: thread-local accumulation with final merge
10.6 Performance Tips
Aspect
Recommendation
Context size
Keep small; use pointers to large data
Cache lines
Align frequently-accessed fields
Atomics
.monotonic for counters, .release/.acquire for flags