Waits for the first value available from any of the channels. Returns an Awaitable that completes with a Result containing the channel index and the received value. Values consumed by non-winning channels are re-sent back to those channels to prevent message loss. This may re
()
| 83 | * @return an awaitable result indicating which channel produced the value |
| 84 | */ |
| 85 | @SuppressWarnings("unchecked") |
| 86 | public Awaitable<Result> select() { |
| 87 | CompletableFuture<Result> winner = new CompletableFuture<>(); |
| 88 | AtomicBoolean won = new AtomicBoolean(); |
| 89 | for (int i = 0; i < channels.size(); i++) { |
| 90 | final int index = i; |
| 91 | AsyncChannel<?> ch = channels.get(i); |
| 92 | ch.receive().toCompletableFuture().whenComplete((value, error) -> { |
| 93 | if (error != null) return; |
| 94 | if (won.compareAndSet(false, true)) { |
| 95 | winner.complete(new Result(index, value)); |
| 96 | } else { |
| 97 | // Re-send the consumed value back to avoid message loss |
| 98 | try { |
| 99 | ((AsyncChannel<Object>) ch).send(value); |
| 100 | } catch (ChannelClosedException ignored) { |
| 101 | // Channel was closed; value cannot be preserved |
| 102 | } |
| 103 | } |
| 104 | }); |
| 105 | } |
| 106 | return GroovyPromise.of(winner); |
| 107 | } |
| 108 | |
| 109 | /** |
| 110 | * The result of a {@link #select()} operation, indicating which |
nothing calls this directly
no test coverage detected