Class AsyncSupport

java.lang.Object
org.apache.groovy.runtime.async.AsyncSupport

public class AsyncSupport extends Object
Internal runtime support for the async/await/defer language features.

This class contains the actual implementation invoked by compiler-generated code. User code should prefer the static methods on Awaitable for combinators and configuration.

Thread pool configuration:

  • On JDK 21+ the default executor is a virtual-thread-per-task executor. Virtual threads make blocking within await() essentially free.
  • On JDK 17-20 the fallback is a cached daemon thread pool whose maximum size is controlled by the system property groovy.async.parallelism (default: 256).
  • The executor can be overridden at any time via setExecutor(java.util.concurrent.Executor).

Exception handling follows a transparency principle: the original exception is rethrown without being wrapped.

Since:
6.0.0
See Also:
  • Method Details

    • isVirtualThreadsAvailable

      public static boolean isVirtualThreadsAvailable()
      Returns true if running on JDK 21+ with virtual thread support.
    • getExecutor

      public static Executor getExecutor()
      Returns the current executor used for async tasks.
    • setExecutor

      public static void setExecutor(Executor executor)
      Sets the executor used for async tasks.
    • resetExecutor

      public static void resetExecutor()
      Resets the executor to the default (virtual threads on JDK 21+, cached pool otherwise).
    • await

      public static <T> T await(Awaitable<T> awaitable)
      Awaits the result of an Awaitable. Blocks the calling thread until the computation completes. The original exception is rethrown transparently.
    • await

      public static <T> T await(CompletableFuture<T> future)
      Awaits a CompletableFuture using non-interruptible join().
    • await

      public static <T> T await(CompletionStage<T> stage)
      Awaits a CompletionStage by converting to CompletableFuture.
    • await

      public static <T> T await(Future<T> future)
      Awaits a Future. Delegates to the CF overload if applicable.
    • await

      public static <T> T await(Object source)
      Awaits an arbitrary object by adapting it via Awaitable.from(Object). This is the fallback overload called by compiler-generated await expressions.
    • executeAsync

      public static <T> Awaitable<T> executeAsync(Closure<T> closure, Executor executor)
      Executes the given closure asynchronously on the specified executor, returning an Awaitable.
    • async

      public static <T> Awaitable<T> async(Closure<T> closure)
      Executes the given closure asynchronously using the default executor.
    • go

      public static <T> Awaitable<T> go(Closure<T> closure)
      Lightweight task spawn. Executes the closure asynchronously using the default executor.
    • wrapAsync

      public static <T> Closure<Awaitable<T>> wrapAsync(Closure<T> closure)
      Wraps a closure so that each invocation executes the body asynchronously and returns an Awaitable. This is the runtime entry point for the async { ... } expression syntax.
       def task = async { expensiveWork() }
       def result = await task()  // explicit call required
       
    • yieldReturn

      public static void yieldReturn(Object bridge, Object value)
      Called by compiler-generated code for yield return expr inside an async generator closure. Delegates to the bridge's yield method.
      Parameters:
      bridge - the GeneratorBridge instance (injected as synthetic parameter)
      value - the value to yield
    • wrapAsyncGenerator

      public static <T> Closure<Iterable<T>> wrapAsyncGenerator(Closure<?> closure)
      Wraps a generator closure so that each invocation returns an Iterable backed by a GeneratorBridge. The generator runs on a background thread and yields values via the bridge.

      This is the runtime entry point for async { ... yield return ... } expressions that contain yield return.

      Type Parameters:
      T - the element type
      Parameters:
      closure - the generator closure; receives a GeneratorBridge as first parameter
      Returns:
      a closure that produces an Iterable when called
    • asyncGenerator

      public static <T> Iterable<T> asyncGenerator(Closure<?> closure)
      Starts a generator immediately, returning an Iterable backed by a GeneratorBridge. This is the runtime entry point for async { ... yield return ... } expressions.
      Type Parameters:
      T - the element type
      Parameters:
      closure - the generator closure; receives a GeneratorBridge as first parameter
      Returns:
      an Iterable that yields values from the generator
    • toIterable

      public static <T> Iterable<T> toIterable(Object source)
      Converts an arbitrary source to an Iterable for use in for await loops. Handles arrays, collections, iterables, iterators, and adapter-supported types. The returned iterable may block on next() for async sources.
      Type Parameters:
      T - the element type
      Parameters:
      source - the source to convert
      Returns:
      an iterable
    • closeIterable

      public static void closeIterable(Object source)
      Closes a source if it implements Closeable or AutoCloseable. Called by compiler-generated finally block in for await loops.
    • all

      public static <T> List<T> all(Object... sources)
      Waits for all given sources to complete, returning their results in order. Multi-arg await(a, b, c) desugars to this.
    • any

      public static <T> T any(Object... sources)
      Returns the result of the first source to complete (success or failure).
    • first

      public static <T> T first(Object... sources)
      Returns the result of the first source to complete successfully. Only fails when all sources fail.
    • allSettled

      public static List<AwaitResult<Object>> allSettled(Object... sources)
      Waits for all sources to settle (succeed or fail), returning a list of AwaitResult without throwing.
    • allAsync

      public static Awaitable<List<Object>> allAsync(Object... sources)
      Non-blocking variant of all(java.lang.Object...) — returns an Awaitable.
    • anyAsync

      public static <T> Awaitable<T> anyAsync(Object... sources)
      Non-blocking variant of any(java.lang.Object...) — returns an Awaitable.
    • firstAsync

      public static <T> Awaitable<T> firstAsync(Object... sources)
      Non-blocking variant of first(java.lang.Object...) — returns an Awaitable.
    • allSettledAsync

      public static Awaitable<List<AwaitResult<Object>>> allSettledAsync(Object... sources)
      Non-blocking variant of allSettled(java.lang.Object...) — returns an Awaitable.
    • delay

      public static Awaitable<Void> delay(long millis)
      Returns an Awaitable that completes after the specified delay.
    • delay

      public static Awaitable<Void> delay(long duration, TimeUnit unit)
      Delay with explicit time unit.
    • orTimeout

      public static <T> Awaitable<T> orTimeout(Object source, long timeout, TimeUnit unit)
      Wraps a source with a timeout. If the source does not complete within the specified time, the returned Awaitable fails with TimeoutException.
    • orTimeoutMillis

      public static <T> Awaitable<T> orTimeoutMillis(Object source, long millis)
      Convenience: timeout in milliseconds.
    • completeOnTimeout

      public static <T> Awaitable<T> completeOnTimeout(Object source, T fallback, long timeout, TimeUnit unit)
      Wraps a source with a timeout that uses a fallback value instead of throwing.
    • completeOnTimeoutMillis

      public static <T> Awaitable<T> completeOnTimeoutMillis(Object source, T fallback, long millis)
      Convenience: timeout in milliseconds.
    • createDeferScope

      public static Deque<Closure<?>> createDeferScope()
      Creates a new defer scope (LIFO stack of cleanup actions). Called by compiler-generated code at the start of closures containing defer statements.
    • defer

      public static void defer(Deque<Closure<?>> scope, Closure<?> action)
      Registers a deferred action in the given scope. Actions execute in LIFO order when executeDeferScope(java.util.Deque<groovy.lang.Closure<?>>) is called (in the finally block).
    • executeDeferScope

      public static void executeDeferScope(Deque<Closure<?>> scope)
      Executes all deferred actions in LIFO order. If multiple actions throw, subsequent exceptions are added as suppressed. If a deferred action returns a Future/Awaitable, the result is awaited before continuing.
    • unwrap

      public static Throwable unwrap(Throwable t)