added LaunchPool
This commit is contained in:
1 parent
145c3ae34a
commit
a8f73dc8bd
9 files changed
+533
-30
No files matched your search
@@ -0,0 +1,110 @@
|
||||
# LaunchPool
|
||||
|
||||
`LaunchPool` is a bounded-concurrency task pool: you submit lambdas with `launch`, and the pool runs them using a fixed number of worker coroutines.
|
||||
|
||||
## Constructor
|
||||
|
||||
```
|
||||
LaunchPool(maxWorkers, maxQueueSize = Channel.UNLIMITED)
|
||||
```
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `maxWorkers` | Maximum number of tasks that run in parallel. |
|
||||
| `maxQueueSize` | Maximum number of tasks that may wait in the queue. When the queue is full, `launch` suspends the caller until space becomes available. Defaults to `Channel.UNLIMITED` (no bound). |
|
||||
|
||||
## Methods
|
||||
|
||||
### `launch(lambda): Deferred`
|
||||
|
||||
Schedules `lambda` for execution and returns a `Deferred` for its result.
|
||||
|
||||
- Suspends if the queue is full (`maxQueueSize` reached).
|
||||
- Throws `IllegalStateException` if the pool is already closed or cancelled.
|
||||
- Any exception thrown by `lambda` is captured in the returned `Deferred` and **does not escape the pool**.
|
||||
|
||||
```lyng
|
||||
val pool = LaunchPool(4)
|
||||
val d1 = pool.launch { computeSomething() }
|
||||
val d2 = pool.launch { computeOther() }
|
||||
pool.closeAndJoin()
|
||||
println(d1.await())
|
||||
println(d2.await())
|
||||
```
|
||||
|
||||
### `closeAndJoin()`
|
||||
|
||||
Stops accepting new tasks and suspends until all queued and running tasks complete normally. After this call, any further `launch` throws `IllegalStateException`. Idempotent — safe to call multiple times.
|
||||
|
||||
### `cancel()`
|
||||
|
||||
Immediately closes the queue and cancels all worker coroutines. Queued but unstarted tasks are discarded. After this call, `launch` throws `IllegalStateException`. Idempotent.
|
||||
|
||||
### `cancelAndJoin()`
|
||||
|
||||
Like `cancel()`, but also suspends until all worker coroutines have stopped. Useful when you need to be sure no worker code is still running before proceeding. Idempotent.
|
||||
|
||||
## Exception handling
|
||||
|
||||
Exceptions from submitted lambdas are captured per-task in the returned `Deferred`. The pool itself continues running after a task failure:
|
||||
|
||||
```lyng
|
||||
val pool = LaunchPool(2)
|
||||
val good = pool.launch { 42 }
|
||||
val bad = pool.launch { throw IllegalArgumentException("boom") }
|
||||
pool.closeAndJoin()
|
||||
|
||||
assertEquals(42, good.await())
|
||||
assertThrows(IllegalArgumentException) { bad.await() }
|
||||
```
|
||||
|
||||
## Bounded queue / back-pressure
|
||||
|
||||
When `maxQueueSize` is set, the producer suspends if the queue fills up, providing automatic back-pressure:
|
||||
|
||||
```lyng
|
||||
// 1 worker, queue of 2 — producer can be at most 2 tasks ahead of what's running
|
||||
val pool = LaunchPool(1, 2)
|
||||
val d1 = pool.launch { delay(10); "a" }
|
||||
val d2 = pool.launch { delay(10); "b" }
|
||||
val d3 = pool.launch { delay(10); "c" } // suspends until d1 is picked up by the worker
|
||||
pool.closeAndJoin()
|
||||
```
|
||||
|
||||
## Collecting all results
|
||||
|
||||
`launch` returns a `Deferred`, so you can collect results via `map`:
|
||||
|
||||
```lyng
|
||||
val pool = LaunchPool(4)
|
||||
val jobs = (1..10).map { n -> pool.launch { n * n } }
|
||||
pool.closeAndJoin()
|
||||
val results = jobs.map { (it as Deferred).await() }
|
||||
// results == [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
|
||||
```
|
||||
|
||||
## Concurrency limit in practice
|
||||
|
||||
With `maxWorkers = 2`, at most 2 tasks run simultaneously regardless of how many are queued:
|
||||
|
||||
```lyng
|
||||
val mu = Mutex()
|
||||
var active = 0
|
||||
var maxSeen = 0
|
||||
|
||||
val pool = LaunchPool(2)
|
||||
(1..8).map {
|
||||
pool.launch {
|
||||
mu.withLock { active++; if (active > maxSeen) maxSeen = active }
|
||||
delay(5)
|
||||
mu.withLock { active-- }
|
||||
}
|
||||
}
|
||||
pool.closeAndJoin()
|
||||
assert(maxSeen <= 2)
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [parallelism.md](parallelism.md) — `launch`, `Deferred`, `Mutex`, `Channel`, and coroutine basics
|
||||
- [Channel.md](Channel.md) — the underlying channel primitive used by `LaunchPool`
|
||||
Reference in new issue
Block a user