[ 
https://issues.apache.org/jira/browse/GROOVY-9381?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Daniel Sun updated GROOVY-9381:
-------------------------------
    Description: 
h1. Add native async/await support
h2. Summary

Introduce first-class {{{}async{}}}/{{{}await{}}} language support to Groovy, 
enabling developers to write asynchronous code in a sequential, readable style 
— on par with the async/await facilities in JavaScript (ES2017), C# (5.0), 
Kotlin (coroutines), and Swift (5.5).
h2. Motivation

Modern JVM applications are overwhelmingly concurrent. Web services, data 
pipelines, and reactive systems spend most of their time waiting for network 
I/O, database queries, or downstream services. The JVM offers powerful but 
low-level concurrency primitives ({{{}CompletableFuture{}}}, 
{{{}Flow.Publisher{}}}, {{{}ExecutorService{}}}), and while libraries like 
RxJava and Project Reactor raise the abstraction level, they introduce their 
own learning curve and cannot alter the language's control-flow syntax.

Today, a typical three-step async workflow in Groovy looks like this:
{code:groovy}
CompletableFuture.supplyAsync { fetchUserId() }
    .thenCompose { id -> CompletableFuture.supplyAsync { lookupName(id) } }
    .thenCompose { name -> CompletableFuture.supplyAsync { loadProfile(name) } }
    .exceptionally { ex -> handleError(ex) }
{code}
The business logic is obscured by plumbing. Exception handling is decoupled 
from the code that raises exceptions, and the control flow reads inside-out.

With the proposed {{{}async{}}}/{{{}await{}}}, the same logic becomes:
{code:groovy}
async fetchProfile() {
    def id   = await fetchUserIdAsync()
    def name = await lookupNameAsync(id)
    return await loadProfileAsync(name)
}
{code}
This reads identically to synchronous code. Standard {{{}try{}}}/{{{}catch{}}}, 
{{{}for{}}}, {{{}if{}}}, and variable assignment all compose naturally — no 
callbacks, no chained lambdas.
h2. Scope

This proposal introduces the following language constructs and runtime APIs:
h3. Language Constructs
||Construct||Syntax||Description||
|Async method|async ReturnType methodName(params) \{ ... }|Declares a method 
that executes asynchronously and returns {{Awaitable<T>}}|
|Await expression|{{await expr}} / {{await(expr)}}|Suspends the enclosing async 
context until the awaited computation completes; transparently unwraps the 
result|
|Async closure / lambda|async \{ params -> body } / async (params) -> \{ body 
}|Creates a reusable asynchronous function (must be explicitly invoked to start 
execution)|
|For-await loop|for await (item in source) \{ ... }|Iterates over an 
{{{}AsyncStream{}}}, {{{}Flow.Publisher{}}}, or {{{}Iterable{}}}, resolving 
each element asynchronously|
|Yield return|{{yield return expr}}|Emits a value from an async generator 
method, producing an {{AsyncStream<T>}} with natural back-pressure|
|Defer|defer \{ cleanup }|Schedules a cleanup block to execute on method exit 
(LIFO order), inspired by Go's {{defer}}|
|@Async annotation|{{@Async}} on method declarations|Annotation equivalent of 
the {{async}} keyword modifier, for interoperability with annotation-processing 
tools|
h3. Public API ({{{}groovy.concurrent{}}} package)
||Class/Interface||Role||
|{{Awaitable<T>}}|Core promise abstraction (analogous to C#'s {{Task<T>}} / 
JS's {{{}Promise<T>{}}}). Provides static combinators ({{{}all{}}}, 
{{{}any{}}}, {{{}allSettled{}}}, {{{}delay{}}}, {{{}timeout{}}}, 
{{{}timeoutOr{}}}), factories ({{{}of{}}}, {{{}failed{}}}), and instance 
continuation methods ({{{}then{}}}, {{{}thenCompose{}}}, {{{}exceptionally{}}}, 
{{{}orTimeout{}}}, {{{}completeOnTimeout{}}})|
|{{AsyncStream<T>}}|Asynchronous iteration abstraction (analogous to C#'s 
{{{}IAsyncEnumerable<T>{}}}). Supports {{{}moveNext(){}}}/{{{}getCurrent(){}}} 
pull-based consumption with {{AutoCloseable}} semantics|
|{{AwaitResult<T>}}|Outcome wrapper returned by {{allSettled()}} — carries 
either a success value or a failure throwable|
|{{AwaitableAdapter}}|SPI interface for adapting third-party async types 
(RxJava, Reactor, Spring) to {{{}Awaitable{}}}/{{{}AsyncStream{}}}|
|{{AwaitableAdapterRegistry}}|Central adapter registry with {{ServiceLoader}} 
auto-discovery and runtime registration|
h3. Internal Runtime ({{{}org.apache.groovy.runtime.async{}}} package)
||Class||Role||
|{{AsyncSupport}}|Central runtime entry point — all {{await}} overloads, 
{{async}} execution, {{defer}} scope management, combinator implementation, 
timeout scheduling, {{yield return}} dispatch|
|{{GroovyPromise<T>}}|Default {{Awaitable}} implementation backed by 
{{{}CompletableFuture{}}}. Sole bridge between the public API and JDK async 
infrastructure|
|{{AsyncStreamGenerator<T>}}|Producer/consumer {{AsyncStream}} implementation 
using {{SynchronousQueue}} for zero-buffered back-pressure with cooperative 
cancellation via thread tracking|
h2. Design Principles
 # *Readability first.* Async code should be visually indistinguishable from 
synchronous code. All standard Groovy control-flow constructs 
({{{}try{}}}/{{{}catch{}}}, {{{}for{}}}, {{{}if{}}}/{{{}else{}}}, closures) 
must work naturally inside async methods.
 # *Exception transparency.* {{await}} automatically unwraps 
{{{}CompletionException{}}}, {{{}ExecutionException{}}}, and other JVM wrapper 
layers. The original exception type, message, and stack trace are preserved — 
callers see the same exceptions they would in synchronous code.
 # *API decoupling.* User code depends on {{{}Awaitable{}}}, not on 
{{{}CompletableFuture{}}}. The public API ({{{}groovy.concurrent{}}}) is 
separated from the internal implementation 
({{{}org.apache.groovy.runtime.async{}}}). If the JDK's async infrastructure 
evolves (e.g., structured concurrency), only the internal layer changes.
 # *Minimal grammar footprint.* {{{}async{}}}, {{{}await{}}}, {{{}defer{}}}, 
and {{yield}} are contextual keywords — they remain valid identifiers in 
non-async contexts, preserving backward compatibility. Grammar changes to 
{{GroovyLexer.g4}} and {{GroovyParser.g4}} are minimal.
 # *Thread safety is the framework's responsibility.* All concurrency control 
(atomics, volatile, CAS) is encapsulated in the runtime. Application code never 
needs explicit locks, synchronization, or volatile annotations.
 # *JVM ecosystem integration.* Built-in adapters handle 
{{{}CompletableFuture{}}}, {{{}CompletionStage{}}}, {{{}Future{}}}, and 
{{Flow.Publisher}} out of the box. Third-party frameworks integrate via the 
{{AwaitableAdapterRegistry}} SPI.

h2. Execution Model

On {*}JDK 21+{*}, each {{async}} method runs on a virtual thread. When the 
thread blocks on {{{}await{}}}, the JVM parks the virtual thread and releases 
the carrier (OS) thread. This achieves the practical scalability of 
compiler-generated state machines (as in C# and Kotlin) without requiring 
control-flow rewriting — stack traces remain complete, and standard debuggers 
work unmodified.

On {*}JDK 17–20{*}, a bounded cached thread pool (default 256, configurable via 
{{{}groovy.async.parallelism{}}}) with a caller-runs back-pressure policy 
provides stable performance.

The executor is fully configurable at runtime via 
{{{}Awaitable.setExecutor(executor){}}}.
h2. Key Features in Detail
h3. Combinators
||Method||Analogy||Behavior||
|{{Awaitable.all(a, b, c)}}|{{Promise.all()}} / {{Task.WhenAll()}}|Waits for 
all; fails fast on first error|
|{{Awaitable.any(a, b)}}|{{Promise.race()}} / {{Task.WhenAny()}}|Returns the 
first to complete|
|{{Awaitable.allSettled(a, b)}}|{{Promise.allSettled()}}|Waits for all; 
captures both successes and failures in {{AwaitResult}} list|
|{{Awaitable.delay(ms)}}|{{Task.Delay()}} / {{setTimeout}}|Non-blocking timer|
|{{Awaitable.timeout(source, ms)}}|{{withTimeout}}|Fails with 
{{TimeoutException}} on expiry|
|{{Awaitable.timeoutOr(source, fallback, ms)}}|—|Completes with fallback value 
on expiry|
h3. Async Generators and Back-Pressure

Methods containing {{yield return}} produce an {{{}AsyncStream<T>{}}}, 
consumable via {{{}for await{}}}. The producer and consumer coordinate through 
a {{SynchronousQueue}} — the producer blocks on each {{yield return}} until the 
consumer pulls the next element, providing natural back-pressure without 
unbounded buffering. If the consumer exits early ({{{}break{}}}, 
{{{}return{}}}, exception), the producer thread is interrupted via cooperative 
cancellation, preventing resource leaks.
h3. Defer (Go-Style Cleanup)

The {{defer}} keyword schedules cleanup actions that execute in LIFO order when 
the enclosing method returns, regardless of success or failure. If multiple 
deferred blocks throw, the first exception is primary and subsequent ones are 
attached via {{{}addSuppressed(){}}}. This provides deterministic resource 
cleanup without deeply nested {{{}try{}}}/{{{}finally{}}} blocks.
h3. Adapter Registry (Third-Party Integration)

The {{AwaitableAdapterRegistry}} is an SPI-based extension point. Adapters can 
be registered:
 * At class-load time via {{ServiceLoader}} 
({{{}META-INF/services/groovy.concurrent.AwaitableAdapter{}}})
 * At runtime via {{AwaitableAdapterRegistry.register(adapter)}}

This enables {{await}} to work transparently with RxJava 
{{{}Single{}}}/{{{}Observable{}}}, Reactor {{{}Mono{}}}/{{{}Flux{}}}, Spring 
{{{}ListenableFuture{}}}, or any custom async type — a single {{await}} 
keyword, regardless of the underlying library.
h2. Thread Safety Mechanisms

All concurrency control is internal and transparent to users:
 * *Lock-free synchronization* — {{volatile}} fields, {{{}AtomicBoolean{}}}, 
{{{}AtomicReference{}}}, {{CopyOnWriteArrayList}} used throughout; no 
{{synchronized}} blocks
 * *TOCTOU prevention* — {{AsyncStreamGenerator.moveNext()}} employs a 
double-check pattern after registering the consumer thread, closing a race 
window with concurrent {{close()}}
 * *Cooperative cancellation* — {{close()}} atomically sets a closed flag and 
interrupts both producer and consumer threads via tracked 
{{AtomicReference<Thread>}}
 * *Signal delivery under interrupt* — If {{{}complete(){}}}/{{{}error(){}}} is 
interrupted and the non-blocking fallback fails, the generator force-closes to 
prevent consumer thread leak
 * *Idempotent close* — All close operations use {{compareAndSet}} and are safe 
to call multiple times from any thread

h2. Cross-Language Comparison
||Aspect||Groovy||JavaScript||C#||Kotlin||Swift||
|Async declaration|async foo() \{ }|{{async function foo()}}|{{async Task<T> 
Foo()}}|{{suspend fun foo(): T}}|{{func foo() async throws -> T}}|
|Await|{{await expr}}|{{await expr}}|{{await expr}}|{{deferred.await()}}|{{try 
await expr}}|
|Async iteration|{{for await (x in src)}}|{{for await (x of src)}}|{{await 
foreach (x in src)}}|manual ({{{}Flow.collect{}}})|{{for try await x in seq}}|
|Async generator|{{yield return expr}}|{{yield}} in {{async function*}}|{{yield 
return}} in {{IAsyncEnumerable}}|flow { emit( x ) }|AsyncStream { yield( x ) }|
|Defer|defer \{ ... }|_(none)_|{{await using}}|{{use}}|{{defer}}|
|Implementation|Thread-per-task (VT on 21+)|Event loop|State machine|Coroutine 
SM|Async SM|
h2. Backward Compatibility
 * {{{}async{}}}, {{{}await{}}}, {{{}defer{}}}, and {{yield}} are *contextual 
keywords* — they act as keywords only in specific syntactic positions and 
remain valid identifiers elsewhere. Existing code using these as variable 
names, method names, or field names continues to compile and run without 
modification.
 * No existing public APIs are modified or removed.
 * The feature is purely additive: code that does not use 
{{{}async{}}}/{{{}await{}}} is entirely unaffected.

  was:
Here is an example to show proposed syntax and backend API(Java's 
{{CompletableFuture}} or GPars's {{{}Promise{}}}), but I think it's better for 
Groovy to have its own {{Promise}} to decouple with Java API because 
async/await as a language feature should be as stable as possible.

{{async}} will generate the {{Awaitable}} instance such as Groovy {{Promise}} 
implementing the {{Awaitable}} interface, and {{await}} can wait for any 
{{Awaitable}} instance to complete and unwrap it for the result. 
{code:java}
/**
 * 1. An async function that simulates a network API call.
 * The 'async' keyword implies it runs asynchronously without blocking.
 */
async fetchUserData(userId) {
    println "Starting to fetch data for user ${userId}..."
    
    // Simulate a 1-second network delay.
    Thread.sleep(1000) 
    
    println "Fetch successful!"
    // The 'async' function implicitly returns a "CompletableFuture" or 
"Promise" containing this value.
    return [userId: userId, name: 'Daniel']
}

/**
 * 2. An async function that uses 'await' to consume the result.
 */
async processUserData() {
    println "Process started, preparing to fetch user data..."
    
    try {
        // 'await' pauses this function until fetchUserData completes
        // and returns the final result directly.
        def user = await fetchUserData(1)
        
        println "Data received: ${user}"
        return "Processing complete for ${user.name}."
        
    } catch (Exception e) {
        return "An error occurred: ${e.message}"
    }
}


// --- Execution ---
println "Script starting..."

// Kick off the entire asynchronous process.
def future = processUserData()

// This line executes immediately, proving the process is non-blocking.
println "Script continues to run while user data is being fetched in the 
background..."

def result = future.get()

println "Script finished: ${result}"
{code}
Use async/await with closure or lambda expression:
{code}
// use closure
def c = async {
    println "Process started, preparing to fetch user data..."
    
    try {
        // 'await' pauses this function until fetchUserData completes
        // and returns the final result directly.
        def user = await fetchUserData(1)
        
        println "Data received: ${user}"
        return "Processing complete for ${user.name}."
        
    } catch (Exception e) {
        return "An error occurred: ${e.message}"
    }
}

def future = c()
{code}

{code}
// use lambda expression
def c = async () -> {
    println "Process started, preparing to fetch user data..."
    
    try {
        // 'await' pauses this function until fetchUserData completes
        // and returns the final result directly.
        def user = await fetchUserData(1)
        
        println "Data received: ${user}"
        return "Processing complete for ${user.name}."
        
    } catch (Exception e) {
        return "An error occurred: ${e.message}"
    }
}

def future = c()
 {code}


> Support async/await like ES7
> ----------------------------
>
>                 Key: GROOVY-9381
>                 URL: https://issues.apache.org/jira/browse/GROOVY-9381
>             Project: Groovy
>          Issue Type: New Feature
>            Reporter: Daniel Sun
>            Priority: Major
>
> h1. Add native async/await support
> h2. Summary
> Introduce first-class {{{}async{}}}/{{{}await{}}} language support to Groovy, 
> enabling developers to write asynchronous code in a sequential, readable 
> style — on par with the async/await facilities in JavaScript (ES2017), C# 
> (5.0), Kotlin (coroutines), and Swift (5.5).
> h2. Motivation
> Modern JVM applications are overwhelmingly concurrent. Web services, data 
> pipelines, and reactive systems spend most of their time waiting for network 
> I/O, database queries, or downstream services. The JVM offers powerful but 
> low-level concurrency primitives ({{{}CompletableFuture{}}}, 
> {{{}Flow.Publisher{}}}, {{{}ExecutorService{}}}), and while libraries like 
> RxJava and Project Reactor raise the abstraction level, they introduce their 
> own learning curve and cannot alter the language's control-flow syntax.
> Today, a typical three-step async workflow in Groovy looks like this:
> {code:groovy}
> CompletableFuture.supplyAsync { fetchUserId() }
>     .thenCompose { id -> CompletableFuture.supplyAsync { lookupName(id) } }
>     .thenCompose { name -> CompletableFuture.supplyAsync { loadProfile(name) 
> } }
>     .exceptionally { ex -> handleError(ex) }
> {code}
> The business logic is obscured by plumbing. Exception handling is decoupled 
> from the code that raises exceptions, and the control flow reads inside-out.
> With the proposed {{{}async{}}}/{{{}await{}}}, the same logic becomes:
> {code:groovy}
> async fetchProfile() {
>     def id   = await fetchUserIdAsync()
>     def name = await lookupNameAsync(id)
>     return await loadProfileAsync(name)
> }
> {code}
> This reads identically to synchronous code. Standard 
> {{{}try{}}}/{{{}catch{}}}, {{{}for{}}}, {{{}if{}}}, and variable assignment 
> all compose naturally — no callbacks, no chained lambdas.
> h2. Scope
> This proposal introduces the following language constructs and runtime APIs:
> h3. Language Constructs
> ||Construct||Syntax||Description||
> |Async method|async ReturnType methodName(params) \{ ... }|Declares a method 
> that executes asynchronously and returns {{Awaitable<T>}}|
> |Await expression|{{await expr}} / {{await(expr)}}|Suspends the enclosing 
> async context until the awaited computation completes; transparently unwraps 
> the result|
> |Async closure / lambda|async \{ params -> body } / async (params) -> \{ body 
> }|Creates a reusable asynchronous function (must be explicitly invoked to 
> start execution)|
> |For-await loop|for await (item in source) \{ ... }|Iterates over an 
> {{{}AsyncStream{}}}, {{{}Flow.Publisher{}}}, or {{{}Iterable{}}}, resolving 
> each element asynchronously|
> |Yield return|{{yield return expr}}|Emits a value from an async generator 
> method, producing an {{AsyncStream<T>}} with natural back-pressure|
> |Defer|defer \{ cleanup }|Schedules a cleanup block to execute on method exit 
> (LIFO order), inspired by Go's {{defer}}|
> |@Async annotation|{{@Async}} on method declarations|Annotation equivalent of 
> the {{async}} keyword modifier, for interoperability with 
> annotation-processing tools|
> h3. Public API ({{{}groovy.concurrent{}}} package)
> ||Class/Interface||Role||
> |{{Awaitable<T>}}|Core promise abstraction (analogous to C#'s {{Task<T>}} / 
> JS's {{{}Promise<T>{}}}). Provides static combinators ({{{}all{}}}, 
> {{{}any{}}}, {{{}allSettled{}}}, {{{}delay{}}}, {{{}timeout{}}}, 
> {{{}timeoutOr{}}}), factories ({{{}of{}}}, {{{}failed{}}}), and instance 
> continuation methods ({{{}then{}}}, {{{}thenCompose{}}}, 
> {{{}exceptionally{}}}, {{{}orTimeout{}}}, {{{}completeOnTimeout{}}})|
> |{{AsyncStream<T>}}|Asynchronous iteration abstraction (analogous to C#'s 
> {{{}IAsyncEnumerable<T>{}}}). Supports 
> {{{}moveNext(){}}}/{{{}getCurrent(){}}} pull-based consumption with 
> {{AutoCloseable}} semantics|
> |{{AwaitResult<T>}}|Outcome wrapper returned by {{allSettled()}} — carries 
> either a success value or a failure throwable|
> |{{AwaitableAdapter}}|SPI interface for adapting third-party async types 
> (RxJava, Reactor, Spring) to {{{}Awaitable{}}}/{{{}AsyncStream{}}}|
> |{{AwaitableAdapterRegistry}}|Central adapter registry with {{ServiceLoader}} 
> auto-discovery and runtime registration|
> h3. Internal Runtime ({{{}org.apache.groovy.runtime.async{}}} package)
> ||Class||Role||
> |{{AsyncSupport}}|Central runtime entry point — all {{await}} overloads, 
> {{async}} execution, {{defer}} scope management, combinator implementation, 
> timeout scheduling, {{yield return}} dispatch|
> |{{GroovyPromise<T>}}|Default {{Awaitable}} implementation backed by 
> {{{}CompletableFuture{}}}. Sole bridge between the public API and JDK async 
> infrastructure|
> |{{AsyncStreamGenerator<T>}}|Producer/consumer {{AsyncStream}} implementation 
> using {{SynchronousQueue}} for zero-buffered back-pressure with cooperative 
> cancellation via thread tracking|
> h2. Design Principles
>  # *Readability first.* Async code should be visually indistinguishable from 
> synchronous code. All standard Groovy control-flow constructs 
> ({{{}try{}}}/{{{}catch{}}}, {{{}for{}}}, {{{}if{}}}/{{{}else{}}}, closures) 
> must work naturally inside async methods.
>  # *Exception transparency.* {{await}} automatically unwraps 
> {{{}CompletionException{}}}, {{{}ExecutionException{}}}, and other JVM 
> wrapper layers. The original exception type, message, and stack trace are 
> preserved — callers see the same exceptions they would in synchronous code.
>  # *API decoupling.* User code depends on {{{}Awaitable{}}}, not on 
> {{{}CompletableFuture{}}}. The public API ({{{}groovy.concurrent{}}}) is 
> separated from the internal implementation 
> ({{{}org.apache.groovy.runtime.async{}}}). If the JDK's async infrastructure 
> evolves (e.g., structured concurrency), only the internal layer changes.
>  # *Minimal grammar footprint.* {{{}async{}}}, {{{}await{}}}, {{{}defer{}}}, 
> and {{yield}} are contextual keywords — they remain valid identifiers in 
> non-async contexts, preserving backward compatibility. Grammar changes to 
> {{GroovyLexer.g4}} and {{GroovyParser.g4}} are minimal.
>  # *Thread safety is the framework's responsibility.* All concurrency control 
> (atomics, volatile, CAS) is encapsulated in the runtime. Application code 
> never needs explicit locks, synchronization, or volatile annotations.
>  # *JVM ecosystem integration.* Built-in adapters handle 
> {{{}CompletableFuture{}}}, {{{}CompletionStage{}}}, {{{}Future{}}}, and 
> {{Flow.Publisher}} out of the box. Third-party frameworks integrate via the 
> {{AwaitableAdapterRegistry}} SPI.
> h2. Execution Model
> On {*}JDK 21+{*}, each {{async}} method runs on a virtual thread. When the 
> thread blocks on {{{}await{}}}, the JVM parks the virtual thread and releases 
> the carrier (OS) thread. This achieves the practical scalability of 
> compiler-generated state machines (as in C# and Kotlin) without requiring 
> control-flow rewriting — stack traces remain complete, and standard debuggers 
> work unmodified.
> On {*}JDK 17–20{*}, a bounded cached thread pool (default 256, configurable 
> via {{{}groovy.async.parallelism{}}}) with a caller-runs back-pressure policy 
> provides stable performance.
> The executor is fully configurable at runtime via 
> {{{}Awaitable.setExecutor(executor){}}}.
> h2. Key Features in Detail
> h3. Combinators
> ||Method||Analogy||Behavior||
> |{{Awaitable.all(a, b, c)}}|{{Promise.all()}} / {{Task.WhenAll()}}|Waits for 
> all; fails fast on first error|
> |{{Awaitable.any(a, b)}}|{{Promise.race()}} / {{Task.WhenAny()}}|Returns the 
> first to complete|
> |{{Awaitable.allSettled(a, b)}}|{{Promise.allSettled()}}|Waits for all; 
> captures both successes and failures in {{AwaitResult}} list|
> |{{Awaitable.delay(ms)}}|{{Task.Delay()}} / {{setTimeout}}|Non-blocking timer|
> |{{Awaitable.timeout(source, ms)}}|{{withTimeout}}|Fails with 
> {{TimeoutException}} on expiry|
> |{{Awaitable.timeoutOr(source, fallback, ms)}}|—|Completes with fallback 
> value on expiry|
> h3. Async Generators and Back-Pressure
> Methods containing {{yield return}} produce an {{{}AsyncStream<T>{}}}, 
> consumable via {{{}for await{}}}. The producer and consumer coordinate 
> through a {{SynchronousQueue}} — the producer blocks on each {{yield return}} 
> until the consumer pulls the next element, providing natural back-pressure 
> without unbounded buffering. If the consumer exits early ({{{}break{}}}, 
> {{{}return{}}}, exception), the producer thread is interrupted via 
> cooperative cancellation, preventing resource leaks.
> h3. Defer (Go-Style Cleanup)
> The {{defer}} keyword schedules cleanup actions that execute in LIFO order 
> when the enclosing method returns, regardless of success or failure. If 
> multiple deferred blocks throw, the first exception is primary and subsequent 
> ones are attached via {{{}addSuppressed(){}}}. This provides deterministic 
> resource cleanup without deeply nested {{{}try{}}}/{{{}finally{}}} blocks.
> h3. Adapter Registry (Third-Party Integration)
> The {{AwaitableAdapterRegistry}} is an SPI-based extension point. Adapters 
> can be registered:
>  * At class-load time via {{ServiceLoader}} 
> ({{{}META-INF/services/groovy.concurrent.AwaitableAdapter{}}})
>  * At runtime via {{AwaitableAdapterRegistry.register(adapter)}}
> This enables {{await}} to work transparently with RxJava 
> {{{}Single{}}}/{{{}Observable{}}}, Reactor {{{}Mono{}}}/{{{}Flux{}}}, Spring 
> {{{}ListenableFuture{}}}, or any custom async type — a single {{await}} 
> keyword, regardless of the underlying library.
> h2. Thread Safety Mechanisms
> All concurrency control is internal and transparent to users:
>  * *Lock-free synchronization* — {{volatile}} fields, {{{}AtomicBoolean{}}}, 
> {{{}AtomicReference{}}}, {{CopyOnWriteArrayList}} used throughout; no 
> {{synchronized}} blocks
>  * *TOCTOU prevention* — {{AsyncStreamGenerator.moveNext()}} employs a 
> double-check pattern after registering the consumer thread, closing a race 
> window with concurrent {{close()}}
>  * *Cooperative cancellation* — {{close()}} atomically sets a closed flag and 
> interrupts both producer and consumer threads via tracked 
> {{AtomicReference<Thread>}}
>  * *Signal delivery under interrupt* — If {{{}complete(){}}}/{{{}error(){}}} 
> is interrupted and the non-blocking fallback fails, the generator 
> force-closes to prevent consumer thread leak
>  * *Idempotent close* — All close operations use {{compareAndSet}} and are 
> safe to call multiple times from any thread
> h2. Cross-Language Comparison
> ||Aspect||Groovy||JavaScript||C#||Kotlin||Swift||
> |Async declaration|async foo() \{ }|{{async function foo()}}|{{async Task<T> 
> Foo()}}|{{suspend fun foo(): T}}|{{func foo() async throws -> T}}|
> |Await|{{await expr}}|{{await expr}}|{{await 
> expr}}|{{deferred.await()}}|{{try await expr}}|
> |Async iteration|{{for await (x in src)}}|{{for await (x of src)}}|{{await 
> foreach (x in src)}}|manual ({{{}Flow.collect{}}})|{{for try await x in seq}}|
> |Async generator|{{yield return expr}}|{{yield}} in {{async 
> function*}}|{{yield return}} in {{IAsyncEnumerable}}|flow { emit( x ) 
> }|AsyncStream { yield( x ) }|
> |Defer|defer \{ ... }|_(none)_|{{await using}}|{{use}}|{{defer}}|
> |Implementation|Thread-per-task (VT on 21+)|Event loop|State 
> machine|Coroutine SM|Async SM|
> h2. Backward Compatibility
>  * {{{}async{}}}, {{{}await{}}}, {{{}defer{}}}, and {{yield}} are *contextual 
> keywords* — they act as keywords only in specific syntactic positions and 
> remain valid identifiers elsewhere. Existing code using these as variable 
> names, method names, or field names continues to compile and run without 
> modification.
>  * No existing public APIs are modified or removed.
>  * The feature is purely additive: code that does not use 
> {{{}async{}}}/{{{}await{}}} is entirely unaffected.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to