Package groovy.concurrent

# Class DataflowVariable<T>

java.lang.Object
groovy.concurrent.DataflowVariable<T>

Type Parameters:
  `T` - the value type

All Implemented Interfaces:
  `Awaitable<T>`

public class DataflowVariable<T> extends Object implements Awaitable<T>
A single-assignment variable for dataflow-style programming.

A `DataflowVariable` starts unbound. It can be written to exactly once via `bind(Object)` (or the `<<` operator in Groovy). Any thread that reads the variable before it is bound will block until a value becomes available. Once bound, all subsequent reads return the same value immediately.

`DataflowVariable` implements `Awaitable`, so it works naturally with `await`:

     def x = new DataflowVariable()
     def y = new DataflowVariable()

     def z = Awaitable.go { await(x) + await(y) }

     async { x << 10 }
     async { y << 5 }

     println "Result: ${await(z)}"  // 15

Inspired by GPars' `DataflowVariable`, modernised to integrate with Groovy's `async`/`await` and `Awaitable` API.

Since:
  6.0.0
See Also:
  - `Awaitable`
  - `Dataflows`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `DataflowVariable()`
  Creates an unbound dataflow variable.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `bind(T value)`
  Binds this variable to the given value.
  `void`
  `bindError(Throwable error)`
  Binds this variable to an error.
  `boolean`
  `cancel()`
  Attempts to cancel the computation.
  `Awaitable<T>`
  `exceptionally(Function<Throwable,? extends T> fn)`
  Returns a new `Awaitable` that, if this one completes exceptionally, applies the given function to the exception to produce a recovery value.
  `T`
  `get()`
  Blocks until the computation completes and returns the result.
  `T`
  `get(long timeout, TimeUnit unit)`
  Blocks until the computation completes or the timeout expires.
  `boolean`
  `isBound()`
  Returns `true` if this variable has been bound to a value or an error.
  `boolean`
  `isCancelled()`
  Returns `true` if the computation was cancelled before completing normally.
  `boolean`
  `isCompletedExceptionally()`
  Returns `true` if this computation completed exceptionally (including cancellation).
  `boolean`
  `isDone()`
  Returns `true` if the computation has completed (normally, exceptionally, or via cancellation).
  `DataflowVariable<T>`
  `leftShift(T value)`
  Groovy operator overload: `variable << value` binds the value.
  `<U> Awaitable<U>`
  `then(Function<? super T,? extends U> fn)`
  Returns a new `Awaitable` whose result is obtained by applying the given function to this awaitable's result when it completes.
  `<U> Awaitable<U>`
  `thenCompose(Function<? super T,? extends Awaitable<U>> fn)`
  Returns a new `Awaitable` produced by applying the given async function to this awaitable's result, flattening the nested `Awaitable`.
  `CompletableFuture<T>`
  `toCompletableFuture()`
  Converts this `Awaitable` to a JDK `CompletableFuture` for interoperability with APIs that require it.
  `String`
  `toString()`
  Returns the current bound state in a diagnostic form.

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

  ### Methods inherited from interface groovy.concurrent.Awaitable

  `completeOnTimeout, completeOnTimeoutMillis, handle, orTimeout, orTimeoutMillis, thenAccept, whenComplete`

- ## Constructor Details

  - ### DataflowVariable

    public DataflowVariable()
    Creates an unbound dataflow variable.

- ## Method Details

  - ### bind

    public void bind(T value)
    Binds this variable to the given value. Can only be called once; subsequent calls throw `IllegalStateException`.
    Parameters:
      `value` - the value to bind (may be `null`)
    Throws:
      `IllegalStateException` - if already bound

  - ### bindError

    public void bindError(Throwable error)
    Binds this variable to an error. Any thread awaiting the value will receive the exception.
    Parameters:
      `error` - the error to bind
    Throws:
      `IllegalStateException` - if already bound

  - ### isBound

    public boolean isBound()
    Returns `true` if this variable has been bound to a value or an error.

  - ### leftShift

    public DataflowVariable<T> leftShift(T value)
    Groovy operator overload: `variable << value` binds the value.
    Parameters:
      `value` - the value to bind
    Returns:
      this variable (for chaining)

  - ### get

    public T get() throws InterruptedException, ExecutionException
    Blocks until the computation completes and returns the result.
    Specified by:
      `get` in interface `Awaitable<T>`
    Returns:
      the computed result
    Throws:
      `InterruptedException` - if the calling thread is interrupted while waiting
      `ExecutionException` - if the computation completed exceptionally

  - ### get

    public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
    Blocks until the computation completes or the timeout expires.
    Specified by:
      `get` in interface `Awaitable<T>`
    Parameters:
      `timeout` - the maximum time to wait
      `unit` - the time unit of the timeout argument
    Returns:
      the computed result
    Throws:
      `InterruptedException` - if the calling thread is interrupted while waiting
      `ExecutionException` - if the computation completed exceptionally
      `TimeoutException` - if the wait timed out

  - ### isDone

    public boolean isDone()
    Returns `true` if the computation has completed (normally, exceptionally, or via cancellation).
    Specified by:
      `isDone` in interface `Awaitable<T>`
    Returns:
      `true` if complete

  - ### cancel

    public boolean cancel()
    Attempts to cancel the computation. If the computation has not yet started or is still running, it will be cancelled with a `CancellationException`.
    Specified by:
      `cancel` in interface `Awaitable<T>`
    Returns:
      `true` if the computation was successfully cancelled

  - ### isCancelled

    public boolean isCancelled()
    Returns `true` if the computation was cancelled before completing normally.
    Specified by:
      `isCancelled` in interface `Awaitable<T>`
    Returns:
      `true` if cancelled

  - ### isCompletedExceptionally

    public boolean isCompletedExceptionally()
    Returns `true` if this computation completed exceptionally (including cancellation).
    Specified by:
      `isCompletedExceptionally` in interface `Awaitable<T>`
    Returns:
      `true` if completed with an error or cancellation

  - ### then

    public <U> Awaitable<U> then(Function<? super T,? extends U> fn)
    Returns a new `Awaitable` whose result is obtained by applying the given function to this awaitable's result when it completes.
    Specified by:
      `then` in interface `Awaitable<T>`
    Type Parameters:
      `U` - the type of the mapped result
    Parameters:
      `fn` - the mapping function
    Returns:
      a new awaitable holding the mapped result

  - ### thenCompose

    public <U> Awaitable<U> thenCompose(Function<? super T,? extends Awaitable<U>> fn)
    Returns a new `Awaitable` produced by applying the given async function to this awaitable's result, flattening the nested `Awaitable`. This is the monadic `flatMap` operation for awaitables.
    Specified by:
      `thenCompose` in interface `Awaitable<T>`
    Type Parameters:
      `U` - the type of the inner awaitable's result
    Parameters:
      `fn` - the async mapping function that returns an `Awaitable`
    Returns:
      a new awaitable holding the inner result

  - ### exceptionally

    public Awaitable<T> exceptionally(Function<Throwable,? extends T> fn)
    Returns a new `Awaitable` that, if this one completes exceptionally, applies the given function to the exception to produce a recovery value. The throwable passed to the function is deeply unwrapped to strip JDK wrapper layers.
    Specified by:
      `exceptionally` in interface `Awaitable<T>`
    Parameters:
      `fn` - the recovery function
    Returns:
      a new awaitable that recovers from failures

  - ### toCompletableFuture

    public CompletableFuture<T> toCompletableFuture()
    Converts this `Awaitable` to a JDK `CompletableFuture` for interoperability with APIs that require it.
    Specified by:
      `toCompletableFuture` in interface `Awaitable<T>`
    Returns:
      a `CompletableFuture` representing this computation

  - ### toString

    public String toString()
    Returns the current bound state in a diagnostic form.
    Overrides:
      `toString` in class `Object`
    Returns:
      the current state description