Class DefaultAsyncChannel<T>

java.lang.Object
org.apache.groovy.runtime.async.DefaultAsyncChannel<T>
Type Parameters:
T - the payload type
All Implemented Interfaces:
AsyncChannel<T>, Iterable<T>

public final class DefaultAsyncChannel<T> extends Object implements AsyncChannel<T>
Default lock-based implementation of AsyncChannel.

Uses a ReentrantLock to coordinate access to the internal buffer and the waiting-sender/waiting-receiver queues. All operations return Awaitable immediately; the underlying CompletableFuture is completed asynchronously when matching counterparts arrive.

Every operation is arbitrated by a SelectClaim: the branches of a ChannelSelect share their select's claim, and a plain operation carries a private one. The claim is the sole owner of a parked operation's fate — a delivery commits it before it completes the future, and cancellation must commit it before it may touch the future — so a select over sends and receives on several channels commits exactly one transfer, and a losing branch never disturbs its channel.

Both waiting queues are concurrent deques so that a cancelled operation can withdraw itself without taking the channel lock: a ChannelSelect withdraws its losing branches from inside the winning channel's delivery, and taking a second channel's lock there could deadlock against a select completing on that channel.

Since:
6.0.0
See Also:
  • Constructor Details

    • DefaultAsyncChannel

      public DefaultAsyncChannel()
    • DefaultAsyncChannel

      public DefaultAsyncChannel(int capacity)
  • Method Details

    • after

      public static DefaultAsyncChannel<Instant> after(long delay, TimeUnit unit)
      Creates a timer channel: a capacity-1 channel that delivers one value, the Instant at which it fired, once delay has elapsed from this call, and then closes. Closing the channel before it fires cancels the timer, so a timer that is no longer wanted holds no scheduler slot. A delay that is not positive has already elapsed, so the channel is returned already holding its instant and closed: it is ready to a receiver or a select at once, with no scheduler hop.

      Implementation of AsyncChannel.after(long); not part of the channel contract.

      Parameters:
      delay - how long to wait before firing
      unit - the unit of delay
      Returns:
      the timer channel
    • getCapacity

      public int getCapacity()
      Description copied from interface: AsyncChannel
      Returns this channel's buffer capacity.
      Specified by:
      getCapacity in interface AsyncChannel<T>
    • getBufferedSize

      public int getBufferedSize()
      Description copied from interface: AsyncChannel
      Returns the number of values currently buffered.
      Specified by:
      getBufferedSize in interface AsyncChannel<T>
    • isClosed

      public boolean isClosed()
      Description copied from interface: AsyncChannel
      Returns true if this channel has been closed.
      Specified by:
      isClosed in interface AsyncChannel<T>
    • send

      public Awaitable<Void> send(T value)
      Description copied from interface: AsyncChannel
      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.

      Specified by:
      send in interface AsyncChannel<T>
      Parameters:
      value - the value to send; must not be null
      Returns:
      an Awaitable that completes when the send succeeds
    • sendIfUnclaimed

      public Awaitable<Void> sendIfUnclaimed(T value, SelectClaim claim)
      Offers value, but only if claim commits to this branch at the moment the channel could accept it: when a waiting receiver takes it, or when buffer space holds it. A group of offers sharing one claim (the branches of a ChannelSelect) commits exactly one between them; an offer whose claim was committed elsewhere is retired without any effect on the channel — no buffered residue, no lingering waiting sender.

      Internal support for ChannelSelect; not part of the channel contract.

      Parameters:
      value - the value offered for transfer
      claim - the claim shared by the competing offers
      Returns:
      an Awaitable that completes when the send committed, or is cancelled if the claim was taken elsewhere first
    • receive

      public Awaitable<T> receive()
      Description copied from interface: AsyncChannel
      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.

      Specified by:
      receive in interface AsyncChannel<T>
      Returns:
      an Awaitable that yields the next value
    • receiveIfUnclaimed

      public Awaitable<T> receiveIfUnclaimed(SelectClaim claim)
      Receives the next value, but only if claim commits to this branch at the moment this channel would hand the value over. The claim is resolved under the channel lock immediately before the value is dequeued, so a group of offers sharing one claim (the branches of a ChannelSelect) takes exactly one value between them: a branch that loses the claim never touches its channel's contents and is completed as cancelled.

      Internal support for ChannelSelect; not part of the channel contract.

      Parameters:
      claim - the claim shared by the competing offers
      Returns:
      an Awaitable that yields the next value, or is cancelled if the claim was taken elsewhere first
    • close

      public boolean close()
      Description copied from interface: AsyncChannel
      Closes this channel. Idempotent.

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

      Specified by:
      close in interface AsyncChannel<T>
      Returns:
      true if this call actually closed the channel
    • iterator

      public Iterator<T> iterator()
      Returns a blocking iterator that receives values until the channel is closed and drained. Each next() call blocks until a value is available. ChannelClosedException signals end-of-iteration.
      Specified by:
      iterator in interface Iterable<T>
    • toString

      public String toString()
      Overrides:
      toString in class Object