Package: groovy.concurrent

## [Java] Interface AsyncChannel<T>

-     public interface AsyncChannel<T>
      extends Iterable

  An asynchronous channel for inter-task communication with optional buffering.

  A channel coordinates producers and consumers without exposing explicit locks or shared mutable state, following the CSP (Communicating Sequential Processes) paradigm popularized by Go's channels.

  Channels support both unbuffered (rendezvous) and buffered modes:

  - Unbuffered — `create()` or `create(0)`. Each `send` suspends until a matching `receive` arrives.
  - Buffered — `create(n)`. Values are enqueued until the buffer fills, then senders suspend.

  Channels implement Iterable, so they work with `for await` and regular `for` loops — iteration yields received values until the channel is closed and drained:

      def ch = AsyncChannel.create(2)
       async { ch.send('a'); ch.send('b'); ch.close() }
       for await (item in ch) {
           println item   // prints 'a', then 'b'
       }

  Type Parameters:
    `T` - the payload type
  See Also:
    Awaitable
  Since:
    6.0.0

- - ### Methods Summary

    Methods
    Type Params | Return Type | Name and description
    --- | --- | ---
    `` | `public static AsyncChannel<Instant>` | `after(long millis)` Creates a timer channel: a capacity-1 channel that delivers a single value, the Instant at which it fired, once `millis` has elapsed from this call, and then closes.
    `` | `public static AsyncChannel<Instant>` | `after(Duration duration)` Creates a timer channel that fires once `duration` has elapsed; see after(long).
    `` | `public boolean` | `close()` Closes this channel.
    `<T>` | `public static AsyncChannel<T>` | `create()` Creates an unbuffered (rendezvous) channel.
    `<T>` | `public static AsyncChannel<T>` | `create(int capacity)` Creates a channel with the specified buffer capacity.
    `` | `public AsyncChannel<T>` | `filter(Predicate<T> predicate)` Returns a new channel that passes only elements matching the predicate.
    `` | `public int` | `getBufferedSize()` Returns the number of values currently buffered.
    `` | `public int` | `getCapacity()` Returns this channel's buffer capacity.
    `` | `public boolean` | `isClosed()` Returns `true` if this channel has been closed.
    `<R>` | `public AsyncChannel<R>` | `map(Function<T, R> transform)` Returns a new channel that transforms each element using the function.
    `` | `public AsyncChannel<T>` | `merge(AsyncChannel<? extends T> other)` Returns a new channel that receives values from both this channel and the other channel.
    `` | `public Awaitable<T>` | `receive()` Receives the next value from this channel.
    `` | `public Awaitable<Void>` | `send(T value)` Sends a value through this channel.
    `` | `public List<AsyncChannel<T>>` | `split(Predicate<T> predicate)` Returns two new channels: elements matching the predicate go to the first, non-matching to the second.
    `` | `public AsyncChannel<T>` | `tap(AsyncChannel<T> tap)` Returns a new channel that receives all values from this channel while also sending a copy of each value to the tap channel.

  - ### Inherited Methods Summary

    Inherited Methods
    Methods inherited from class | Name
    --- | ---
    `interface Iterable` | `forEach, iterator, spliterator`

- - ### Method Detail

    - #### public static AsyncChannel<Instant> after(long millis)

      Creates a timer channel: a capacity-1 channel that delivers a single value, the Instant at which it fired, once `millis` has elapsed from this call, and then closes.

      Its purpose is to make a deadline a branch of a ChannelSelect, the way Go's `time.After` does, rather than an exception thrown around the whole select by Awaitable.orTimeout:

          def result = await ChannelSelect.from(work, AsyncChannel.after(100)).select()
           if (result.index == 1) {
               // timed out: result.value is the Instant the timer fired
           }

      As a channel, a timer composes with everything a select offers: several timers give per-branch deadlines, a timer may be guarded with ChannelSelect.Offer#when, and ChannelSelect.fair and ChannelSelect.random treat it like any other ready branch.

      The clock starts now, not at the first receive, so a timer created once and reused across selects is a fixed deadline shared by every round. For a per-round timeout that re-arms on each call of a select that is held and reused, use the timer offer ChannelSelect.after instead. A timer that loses a select keeps its value: it fires all the same and holds the instant until received. Once the value has been taken, further receives fail with ChannelClosedException rather than waiting forever, and isClosed() reports that the timer has fired. Closing a timer before it fires cancels it. A delay that is not positive has already elapsed, so the channel is returned already holding its instant: it is ready at once, which suits a deadline computed from an absolute time that has already passed.

      Parameters:
        `millis` - how long to wait before firing, in milliseconds
      Returns:
        a channel that delivers the firing instant and then closes
      See Also:
        after(Duration)
        ChannelSelect
      Since:
        6.0.0

    - #### public static AsyncChannel<Instant> after(Duration duration)

      Creates a timer channel that fires once `duration` has elapsed; see after(long).

      throws:
        NullPointerException if duration is null
      Parameters:
        `duration` - how long to wait before firing
      Returns:
        a channel that delivers the firing instant and then closes
      Since:
        6.0.0

    - #### public boolean close()

      Closes this channel. Idempotent.

      Buffered values remain receivable. Pending senders fail with ChannelClosedException. After all buffered values are drained, subsequent receives also fail.

      Returns:
        `true` if this call actually closed the channel

    - #### <T> public static AsyncChannel<T> create()

      Creates an unbuffered (rendezvous) channel.

    - #### <T> public static AsyncChannel<T> create(int capacity)

      Creates a channel with the specified buffer capacity.

      Parameters:
        `capacity` - the maximum buffer size; 0 for unbuffered

    - #### public AsyncChannel<T> filter(Predicate<T> predicate)

      Returns a new channel that passes only elements matching the predicate.

      Parameters:
        `predicate` - the filter function
      Returns:
        a new filtered channel
      Since:
        6.0.0

    - #### public int getBufferedSize()

      Returns the number of values currently buffered.

    - #### public int getCapacity()

      Returns this channel's buffer capacity.

    - #### public boolean isClosed()

      Returns `true` if this channel has been closed.

    - #### <R> public AsyncChannel<R> map(Function<T, R> transform)

      Returns a new channel that transforms each element using the function.

      Parameters:
        `transform` - the mapping function
      Type Parameters:
        `R` - the output element type
      Returns:
        a new transformed channel
      Since:
        6.0.0

    - #### public AsyncChannel<T> merge(AsyncChannel<? extends T> other)

      Returns a new channel that receives values from both this channel and the other channel. Values are interleaved as they arrive. The output closes when both inputs are exhausted.

      Parameters:
        `other` - the channel to merge with
      Returns:
        a new merged channel
      Since:
        6.0.0

    - #### public Awaitable<T> receive()

      Receives the next value from this channel.

      The returned Awaitable completes when a value is available. Receiving from a closed, empty channel fails with ChannelClosedException.

      Returns:
        an Awaitable that yields the next value

    - #### public Awaitable<Void> send(T value)

      Sends a value through this channel.

      The returned Awaitable completes when the value has been delivered to a receiver or buffered. Sending to a closed channel fails immediately with ChannelClosedException.

      throws:
        NullPointerException if value is null
      Parameters:
        `value` - the value to send; must not be `null`
      Returns:
        an Awaitable that completes when the send succeeds

    - #### public List<AsyncChannel<T>> split(Predicate<T> predicate)

      Returns two new channels: elements matching the predicate go to the first, non-matching to the second. Both are closed when this channel is exhausted.

      Parameters:
        `predicate` - the split condition
      Returns:
        a list of two channels: [matching, non-matching]
      Since:
        6.0.0

    - #### public AsyncChannel<T> tap(AsyncChannel<T> tap)

      Returns a new channel that receives all values from this channel while also sending a copy of each value to the tap channel. Useful for logging, monitoring, or forking a side pipeline.

      Parameters:
        `tap` - the channel to send copies to
      Returns:
        a new pass-through channel
      Since:
        6.0.0