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

Paul King updated GROOVY-9381:
------------------------------
    Description: 
 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 {{async}}/{{await}}, the same logic becomes:                             
                                                                                
                                                                                
                
  {code:groovy}                                                                 
                                                                                
                                                                                
                
  def profile = async {                                                         
                                                                                
                                                                                
                
      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 closure|async \{ ... \}|Starts a closure on a background thread, 
returning an {{Awaitable}} (or {{Iterable}} when the body contains {{yield 
return}})|
  |Await expression|await expr / await(expr)|Blocks until the awaited 
computation completes; transparently unwraps the result|                        
                                                                                
                  
  |Multi-arg await|await(a, b, c) \\ await a, b, c|Syntactic sugar for 
{{Awaitable.all(a, b, c)}}|
  |For-await loop|for await (item in source) \{ ... \}|Iterates over an async 
source (generator, channel, reactive type), with automatic resource cleanup via 
try-finally|                                                                    
                
  |Yield return|yield return expr|Emits a value from an async generator 
closure, producing an {{Iterable}} with natural back-pressure|                  
                                                                                
                    
  |Defer|defer \{ cleanup \} \\ defer cleanup|Schedules a cleanup block to 
execute on closure exit (LIFO order), inspired by Go's {{defer}}|               
                                                                                
                
                                                                                
                                                                                
                                                                                
                
  h3. Public API ({{groovy.concurrent}} package)                                
                                                                                
                                                                                
                
  ||Class/Interface||Role||                                                     
                                                                                
                                                                                
                
  |{{Awaitable}}|Core promise abstraction (analogous to C#'s {{Task}} / JS's 
{{Promise}}). Provides static combinators ({{all}}, {{any}}, {{first}}, 
{{allSettled}}, {{delay}}, {{orTimeout}}, {{completeOnTimeout}}), factories 
({{of}}, {{failed}}, {{from}}, 
  {{go}}), and instance continuation methods ({{then}}, {{thenCompose}}, 
{{thenAccept}}, {{exceptionally}}, {{whenComplete}}, {{handle}}, {{orTimeout}}, 
{{completeOnTimeout}})|                                                         
                       
  |{{AsyncChannel}}|Go-style inter-task communication channel with optional 
buffering. Supports unbuffered (rendezvous) and buffered modes. Implements 
{{Iterable}}, so works with {{for await}} and regular {{for}} loops|
  |{{AsyncScope}}|Structured concurrency scope — binds child task lifetimes to 
a scope with fail-fast cancellation. All children are guaranteed complete (or 
cancelled) before the scope exits|                                              
                   
  |{{AwaitResult}}|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, etc.) to {{Awaitable}}|                                       
                                                                                
                     
  |{{AwaitableAdapterRegistry}}|Central adapter registry with {{ServiceLoader}} 
auto-discovery and runtime registration|                                        
                                                                                
                
  |{{ChannelClosedException}}|Thrown when sending to or receiving from a closed 
channel|                                                                        
                                                                                
                
                                                                                
                                                                                
                                                                                
                
  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, channel and scope support|
  |{{GroovyPromise}}|Default {{Awaitable}} implementation backed by 
{{CompletableFuture}}. Sole bridge between the public API and JDK async 
infrastructure|                                                                 
                                    
  |{{GeneratorBridge}}|Producer/consumer bridge for async generators ({{yield 
return}}). Uses {{SynchronousQueue}} for zero-buffered back-pressure with 
cooperative cancellation via thread tracking. Implements {{Iterator}} and 
{{Closeable}}|                
  |{{DefaultAsyncChannel}}|Default {{AsyncChannel}} implementation with 
buffered and unbuffered modes|                                                  
                                                                                
                        
  |{{DefaultAsyncScope}}|Default {{AsyncScope}} implementation with fail-fast 
child cancellation|                                                             
                                                                                
                  
                                                                                
                                                                                
                                                                                
                
  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 closures.
                                                                                
                                                                                
                                                                                
                
  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}}, and {{Future}} out of the box. Third-party frameworks 
integrate via the {{AwaitableAdapterRegistry}} SPI.                             
                        
                                                            
  h2. Execution Model                                                           
                                                                                
                                                                                
                
                                                            
  On {*}JDK 21+{*}, each {{async}} closure 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 to succeed; fails immediately on first error (fail-fast)|
  |{{Awaitable.any(a, b)}}|{{Promise.any()}}|Returns the first to complete 
(success or failure)|                                                           
                                                                               
  |{{Awaitable.first(a, b, c)}}|{{Promise.race()}} \\ 
{{Task.WhenAny()}}|Returns the first to succeed; fails only when all sources 
fail (aggregate error)|                                                         
                                                                    
  |{{Awaitable.allSettled(a, b)}}|{{Promise.allSettled()}}|Waits for all to 
complete (success or fail); captures outcomes in {{AwaitResult}} list without 
throwing|                                                                       
                      
  |{{Awaitable.delay(ms)}}|{{Task.Delay()}} \\ {{setTimeout}}|Non-blocking 
timer|                                                                          
                                                                                
                      
  |{{Awaitable.orTimeoutMillis(source, ms)}}|{{withTimeout}}|Fails with 
{{TimeoutException}} on expiry|                                                 
                                                                                
                        
  |{{Awaitable.completeOnTimeoutMillis(source, fallback, ms)}}|—|Completes with 
fallback value on expiry|                                                       
                                                                                
                
                                                                                
                                                                                
                                                                                
                
  h3. Async Generators and Back-Pressure                                        
                                                                                
                                                                                
                
                                                                                
                                                                                
                                                                                
                
  Closures containing {{yield return}} produce an {{Iterable}}, consumable via 
{{for await}} or a regular {{for}} loop. The producer and consumer coordinate 
through the {{GeneratorBridge}}, which uses 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. {{for await}} wraps the loop in a try-finally to 
ensure generator cleanup.                                                       
                                                                                
                  
                                                            
  h3. Channels (Go-Style Inter-Task Communication)

  {{AsyncChannel}} provides CSP-style communication between tasks. A producer 
sends values into a channel; a consumer receives them. The channel handles 
synchronization and optional buffering — no shared mutable state needed. 
Channels support unbuffered   
  (rendezvous, {{create()}}) and buffered ({{create\(n)}}) modes. Sending 
blocks when the buffer is full; receiving blocks when empty. Since channels 
implement {{Iterable}}, they work with {{for await}}, regular {{for}} loops, 
and Groovy collection methods.
                                                                                
                                                                                
                                                                                
                
  h3. Structured Concurrency                                                    
                                                                                
                                                                                
                
   
  {{AsyncScope}} binds the lifetime of child tasks to a scope. When the scope 
exits, all children are guaranteed complete (or cancelled). This prevents 
orphaned tasks and silent failures. By default, the scope uses fail-fast 
semantics — if any child fails,
   all siblings are cancelled immediately. On JDK 25+, scope tracking uses 
{{ScopedValue}} for optimal virtual thread performance; on JDK 17–24, a 
{{ThreadLocal}} fallback is used transparently.
                                                                                
                                                                                
                                                                                
                
  h3. Defer (Go-Style Cleanup)                              

  The {{defer}} keyword schedules cleanup actions that execute in LIFO order 
when the enclosing async closure returns, regardless of success or failure. If 
multiple deferred blocks throw, the first exception is primary and subsequent 
ones are attached via 
  {{addSuppressed()}}. If a deferred action returns an {{Awaitable}} or 
{{Future}}, the result is awaited before the next deferred action runs, 
ensuring orderly cleanup of asynchronous resources. 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}}, or any custom async type 
— a single {{await}} keyword, regardless of the underlying library. Drop-in 
adapter modules are provided for:         
  - groovy-reactor — {{await}} on {{Mono}}, {{for await}} over {{Flux}}         
                                                                                
                                                                                
                
  - groovy-rxjava — {{await}} on {{Single}}/{{Maybe}}/{{Completable}}, {{for 
await}} over {{Observable}}/{{Flowable}}                                        
                                                                                
                   
                                                                                
                                                                                
                                                                                
                
  h2. Thread Safety Mechanisms                                                  
                                                                                
                                                                                
                
                                                            
  All concurrency control is internal and transparent to users:
  - Lock-free synchronization — {{volatile}} fields, {{AtomicInteger}}, 
{{AtomicReference}}, {{CopyOnWriteArrayList}} used throughout; no 
{{synchronized}} blocks in the async runtime
  - TOCTOU prevention — {{GeneratorBridge.yield()}} sets {{producerThread}} 
before checking the {{closed}} flag, then re-checks after blocking operations, 
closing a race window with concurrent {{close()}}                               
                     
  - Cooperative cancellation — {{GeneratorBridge.close()}} atomically sets a 
closed flag, drains any pending handoff, and interrupts the producer thread     
                                               
  - Idempotent close — All close operations are safe to call multiple times 
from any thread                                                                 
                                                                                
                    
                                                                                
                                                                                
                                                                                
                
  h2. Cross-Language Comparison                                                 
                                                                                
                                                                                
                
  ||Aspect||Groovy||JavaScript||C#||Kotlin||Swift||                             
                                                                                
                                                                                
                
  |Async declaration|async \{ ... \}|{{async function foo()}}|{{async Task 
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}}|                    
                                                                                
                                                                                
                
  |Channels|{{AsyncChannel}}|(none)|{{Channel}}|{{Channel}}|{{AsyncStream}} 
(limited)|                                                                      
                                                                                
                    
  |Structured 
concurrency|{{AsyncScope}}|(none)|(none)|{{coroutineScope}}|{{TaskGroup}}|      
                                                                                
                                                                                
  
  |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:
 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 {{async}}/{{await}}, the same logic becomes:                             
                                                                                
                                                                                
                
  {code:groovy}                                                                 
                                                                                
                                                                                
                
  def profile = async {                                                         
                                                                                
                                                                                
                
      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 closure|async \{ ... \}|Starts a closure on a background thread, 
returning an {{Awaitable}} (or {{Iterable}} when the body contains {{yield 
return}})|
  |Await expression|await expr / await(expr)|Blocks until the awaited 
computation completes; transparently unwraps the result|                        
                                                                                
                  
  |Multi-arg await|await(a, b, c) \\ await a, b, c|Syntactic sugar for 
{{Awaitable.all(a, b, c)}}|
  |For-await loop|for await (item in source) \{ ... \}|Iterates over an async 
source (generator, channel, reactive type), with automatic resource cleanup via 
try-finally|                                                                    
                
  |Yield return|yield return expr|Emits a value from an async generator 
closure, producing an {{Iterable}} with natural back-pressure|                  
                                                                                
                    
  |Defer|defer \{ cleanup \} \\ defer cleanup|Schedules a cleanup block to 
execute on closure exit (LIFO order), inspired by Go's {{defer}}|               
                                                                                
                
                                                                                
                                                                                
                                                                                
                
  h3. Public API ({{groovy.concurrent}} package)                                
                                                                                
                                                                                
                
  ||Class/Interface||Role||                                                     
                                                                                
                                                                                
                
  |{{Awaitable}}|Core promise abstraction (analogous to C#'s {{Task}} / JS's 
{{Promise}}). Provides static combinators ({{all}}, {{any}}, {{first}}, 
{{allSettled}}, {{delay}}, {{orTimeout}}, {{completeOnTimeout}}), factories 
({{of}}, {{failed}}, {{from}}, 
  {{go}}), and instance continuation methods ({{then}}, {{thenCompose}}, 
{{thenAccept}}, {{exceptionally}}, {{whenComplete}}, {{handle}}, {{orTimeout}}, 
{{completeOnTimeout}})|                                                         
                       
  |{{AsyncChannel}}|Go-style inter-task communication channel with optional 
buffering. Supports unbuffered (rendezvous) and buffered modes. Implements 
{{Iterable}}, so works with {{for await}} and regular {{for}} loops|
  |{{AsyncScope}}|Structured concurrency scope — binds child task lifetimes to 
a scope with fail-fast cancellation. All children are guaranteed complete (or 
cancelled) before the scope exits|                                              
                   
  |{{AwaitResult}}|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, etc.) to {{Awaitable}}|                                       
                                                                                
                     
  |{{AwaitableAdapterRegistry}}|Central adapter registry with {{ServiceLoader}} 
auto-discovery and runtime registration|                                        
                                                                                
                
  |{{ChannelClosedException}}|Thrown when sending to or receiving from a closed 
channel|                                                                        
                                                                                
                
                                                                                
                                                                                
                                                                                
                
  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, channel and scope support|
  |{{GroovyPromise}}|Default {{Awaitable}} implementation backed by 
{{CompletableFuture}}. Sole bridge between the public API and JDK async 
infrastructure|                                                                 
                                    
  |{{GeneratorBridge}}|Producer/consumer bridge for async generators ({{yield 
return}}). Uses {{SynchronousQueue}} for zero-buffered back-pressure with 
cooperative cancellation via thread tracking. Implements {{Iterator}} and 
{{Closeable}}|                
  |{{DefaultAsyncChannel}}|Default {{AsyncChannel}} implementation with 
buffered and unbuffered modes|                                                  
                                                                                
                        
  |{{DefaultAsyncScope}}|Default {{AsyncScope}} implementation with fail-fast 
child cancellation|                                                             
                                                                                
                  
                                                                                
                                                                                
                                                                                
                
  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 closures.
                                                                                
                                                                                
                                                                                
                
  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}}, and {{Future}} out of the box. Third-party frameworks 
integrate via the {{AwaitableAdapterRegistry}} SPI.                             
                        
                                                            
  h2. Execution Model                                                           
                                                                                
                                                                                
                
                                                            
  On {*}JDK 21+{*}, each {{async}} closure 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 to succeed; fails immediately on first error (fail-fast)|
  |{{Awaitable.any(a, b)}}|{{Promise.race()}} \\ {{Task.WhenAny()}}|Returns the 
first to complete (success or failure)|                                         
                                                                                
                 
  |{{Awaitable.first(a, b, c)}}|{{Promise.any()}}|Returns the first to succeed; 
fails only when all sources fail (aggregate error)|                             
                                                                                
                
  |{{Awaitable.allSettled(a, b)}}|{{Promise.allSettled()}}|Waits for all to 
complete (success or fail); captures outcomes in {{AwaitResult}} list without 
throwing|                                                                       
                      
  |{{Awaitable.delay(ms)}}|{{Task.Delay()}} \\ {{setTimeout}}|Non-blocking 
timer|                                                                          
                                                                                
                      
  |{{Awaitable.orTimeoutMillis(source, ms)}}|{{withTimeout}}|Fails with 
{{TimeoutException}} on expiry|                                                 
                                                                                
                        
  |{{Awaitable.completeOnTimeoutMillis(source, fallback, ms)}}|—|Completes with 
fallback value on expiry|                                                       
                                                                                
                
                                                                                
                                                                                
                                                                                
                
  h3. Async Generators and Back-Pressure                                        
                                                                                
                                                                                
                
                                                                                
                                                                                
                                                                                
                
  Closures containing {{yield return}} produce an {{Iterable}}, consumable via 
{{for await}} or a regular {{for}} loop. The producer and consumer coordinate 
through the {{GeneratorBridge}}, which uses 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. {{for await}} wraps the loop in a try-finally to 
ensure generator cleanup.                                                       
                                                                                
                  
                                                            
  h3. Channels (Go-Style Inter-Task Communication)

  {{AsyncChannel}} provides CSP-style communication between tasks. A producer 
sends values into a channel; a consumer receives them. The channel handles 
synchronization and optional buffering — no shared mutable state needed. 
Channels support unbuffered   
  (rendezvous, {{create()}}) and buffered ({{create\(n)}}) modes. Sending 
blocks when the buffer is full; receiving blocks when empty. Since channels 
implement {{Iterable}}, they work with {{for await}}, regular {{for}} loops, 
and Groovy collection methods.
                                                                                
                                                                                
                                                                                
                
  h3. Structured Concurrency                                                    
                                                                                
                                                                                
                
   
  {{AsyncScope}} binds the lifetime of child tasks to a scope. When the scope 
exits, all children are guaranteed complete (or cancelled). This prevents 
orphaned tasks and silent failures. By default, the scope uses fail-fast 
semantics — if any child fails,
   all siblings are cancelled immediately. On JDK 25+, scope tracking uses 
{{ScopedValue}} for optimal virtual thread performance; on JDK 17–24, a 
{{ThreadLocal}} fallback is used transparently.
                                                                                
                                                                                
                                                                                
                
  h3. Defer (Go-Style Cleanup)                              

  The {{defer}} keyword schedules cleanup actions that execute in LIFO order 
when the enclosing async closure returns, regardless of success or failure. If 
multiple deferred blocks throw, the first exception is primary and subsequent 
ones are attached via 
  {{addSuppressed()}}. If a deferred action returns an {{Awaitable}} or 
{{Future}}, the result is awaited before the next deferred action runs, 
ensuring orderly cleanup of asynchronous resources. 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}}, or any custom async type 
— a single {{await}} keyword, regardless of the underlying library. Drop-in 
adapter modules are provided for:         
  - groovy-reactor — {{await}} on {{Mono}}, {{for await}} over {{Flux}}         
                                                                                
                                                                                
                
  - groovy-rxjava — {{await}} on {{Single}}/{{Maybe}}/{{Completable}}, {{for 
await}} over {{Observable}}/{{Flowable}}                                        
                                                                                
                   
                                                                                
                                                                                
                                                                                
                
  h2. Thread Safety Mechanisms                                                  
                                                                                
                                                                                
                
                                                            
  All concurrency control is internal and transparent to users:
  - Lock-free synchronization — {{volatile}} fields, {{AtomicInteger}}, 
{{AtomicReference}}, {{CopyOnWriteArrayList}} used throughout; no 
{{synchronized}} blocks in the async runtime
  - TOCTOU prevention — {{GeneratorBridge.yield()}} sets {{producerThread}} 
before checking the {{closed}} flag, then re-checks after blocking operations, 
closing a race window with concurrent {{close()}}                               
                     
  - Cooperative cancellation — {{GeneratorBridge.close()}} atomically sets a 
closed flag, drains any pending handoff, and interrupts the producer thread     
                                               
  - Idempotent close — All close operations are safe to call multiple times 
from any thread                                                                 
                                                                                
                    
                                                                                
                                                                                
                                                                                
                
  h2. Cross-Language Comparison                                                 
                                                                                
                                                                                
                
  ||Aspect||Groovy||JavaScript||C#||Kotlin||Swift||                             
                                                                                
                                                                                
                
  |Async declaration|async \{ ... \}|{{async function foo()}}|{{async Task 
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}}|                    
                                                                                
                                                                                
                
  |Channels|{{AsyncChannel}}|(none)|{{Channel}}|{{Channel}}|{{AsyncStream}} 
(limited)|                                                                      
                                                                                
                    
  |Structured 
concurrency|{{AsyncScope}}|(none)|(none)|{{coroutineScope}}|{{TaskGroup}}|      
                                                                                
                                                                                
  
  |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.   


> Add native async/await support
> ------------------------------
>
>                 Key: GROOVY-9381
>                 URL: https://issues.apache.org/jira/browse/GROOVY-9381
>             Project: Groovy
>          Issue Type: New Feature
>            Reporter: Daniel Sun
>            Assignee: Daniel Sun
>            Priority: Major
>             Fix For: 6.x
>
>
>  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 {{async}}/{{await}}, the same logic becomes:                           
>                                                                               
>                                                                               
>                       
>   {code:groovy}                                                               
>                                                                               
>                                                                               
>                       
>   def profile = async {                                                       
>                                                                               
>                                                                               
>                       
>       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 closure|async \{ ... \}|Starts a closure on a background thread, 
> returning an {{Awaitable}} (or {{Iterable}} when the body contains {{yield 
> return}})|
>   |Await expression|await expr / await(expr)|Blocks until the awaited 
> computation completes; transparently unwraps the result|                      
>                                                                               
>                       
>   |Multi-arg await|await(a, b, c) \\ await a, b, c|Syntactic sugar for 
> {{Awaitable.all(a, b, c)}}|
>   |For-await loop|for await (item in source) \{ ... \}|Iterates over an async 
> source (generator, channel, reactive type), with automatic resource cleanup 
> via try-finally|                                                              
>                       
>   |Yield return|yield return expr|Emits a value from an async generator 
> closure, producing an {{Iterable}} with natural back-pressure|                
>                                                                               
>                         
>   |Defer|defer \{ cleanup \} \\ defer cleanup|Schedules a cleanup block to 
> execute on closure exit (LIFO order), inspired by Go's {{defer}}|             
>                                                                               
>                     
>                                                                               
>                                                                               
>                                                                               
>                       
>   h3. Public API ({{groovy.concurrent}} package)                              
>                                                                               
>                                                                               
>                       
>   ||Class/Interface||Role||                                                   
>                                                                               
>                                                                               
>                       
>   |{{Awaitable}}|Core promise abstraction (analogous to C#'s {{Task}} / JS's 
> {{Promise}}). Provides static combinators ({{all}}, {{any}}, {{first}}, 
> {{allSettled}}, {{delay}}, {{orTimeout}}, {{completeOnTimeout}}), factories 
> ({{of}}, {{failed}}, {{from}}, 
>   {{go}}), and instance continuation methods ({{then}}, {{thenCompose}}, 
> {{thenAccept}}, {{exceptionally}}, {{whenComplete}}, {{handle}}, 
> {{orTimeout}}, {{completeOnTimeout}})|                                        
>                                         
>   |{{AsyncChannel}}|Go-style inter-task communication channel with optional 
> buffering. Supports unbuffered (rendezvous) and buffered modes. Implements 
> {{Iterable}}, so works with {{for await}} and regular {{for}} loops|
>   |{{AsyncScope}}|Structured concurrency scope — binds child task lifetimes 
> to a scope with fail-fast cancellation. All children are guaranteed complete 
> (or cancelled) before the scope exits|                                        
>                          
>   |{{AwaitResult}}|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, etc.) to {{Awaitable}}|                                     
>                                                                               
>                          
>   |{{AwaitableAdapterRegistry}}|Central adapter registry with 
> {{ServiceLoader}} auto-discovery and runtime registration|                    
>                                                                               
>                                       
>   |{{ChannelClosedException}}|Thrown when sending to or receiving from a 
> closed channel|                                                               
>                                                                               
>                            
>                                                                               
>                                                                               
>                                                                               
>                       
>   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, channel and scope support|
>   |{{GroovyPromise}}|Default {{Awaitable}} implementation backed by 
> {{CompletableFuture}}. Sole bridge between the public API and JDK async 
> infrastructure|                                                               
>                                       
>   |{{GeneratorBridge}}|Producer/consumer bridge for async generators ({{yield 
> return}}). Uses {{SynchronousQueue}} for zero-buffered back-pressure with 
> cooperative cancellation via thread tracking. Implements {{Iterator}} and 
> {{Closeable}}|                
>   |{{DefaultAsyncChannel}}|Default {{AsyncChannel}} implementation with 
> buffered and unbuffered modes|                                                
>                                                                               
>                             
>   |{{DefaultAsyncScope}}|Default {{AsyncScope}} implementation with fail-fast 
> child cancellation|                                                           
>                                                                               
>                       
>                                                                               
>                                                                               
>                                                                               
>                       
>   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 closures.
>                                                                               
>                                                                               
>                                                                               
>                       
>   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}}, and {{Future}} out of the box. Third-party frameworks 
> integrate via the {{AwaitableAdapterRegistry}} SPI.                           
>                           
>                                                             
>   h2. Execution Model                                                         
>                                                                               
>                                                                               
>                       
>                                                             
>   On {*}JDK 21+{*}, each {{async}} closure 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 to succeed; fails immediately on first error (fail-fast)|
>   |{{Awaitable.any(a, b)}}|{{Promise.any()}}|Returns the first to complete 
> (success or failure)|                                                         
>                                                                               
>    
>   |{{Awaitable.first(a, b, c)}}|{{Promise.race()}} \\ 
> {{Task.WhenAny()}}|Returns the first to succeed; fails only when all sources 
> fail (aggregate error)|                                                       
>                                                                       
>   |{{Awaitable.allSettled(a, b)}}|{{Promise.allSettled()}}|Waits for all to 
> complete (success or fail); captures outcomes in {{AwaitResult}} list without 
> throwing|                                                                     
>                         
>   |{{Awaitable.delay(ms)}}|{{Task.Delay()}} \\ {{setTimeout}}|Non-blocking 
> timer|                                                                        
>                                                                               
>                           
>   |{{Awaitable.orTimeoutMillis(source, ms)}}|{{withTimeout}}|Fails with 
> {{TimeoutException}} on expiry|                                               
>                                                                               
>                             
>   |{{Awaitable.completeOnTimeoutMillis(source, fallback, ms)}}|—|Completes 
> with fallback value on expiry|                                                
>                                                                               
>                          
>                                                                               
>                                                                               
>                                                                               
>                       
>   h3. Async Generators and Back-Pressure                                      
>                                                                               
>                                                                               
>                       
>                                                                               
>                                                                               
>                                                                               
>                       
>   Closures containing {{yield return}} produce an {{Iterable}}, consumable 
> via {{for await}} or a regular {{for}} loop. The producer and consumer 
> coordinate through the {{GeneratorBridge}}, which uses 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. {{for await}} wraps the loop in a try-finally to 
> ensure generator cleanup.                                                     
>                                                                               
>                       
>                                                             
>   h3. Channels (Go-Style Inter-Task Communication)
>   {{AsyncChannel}} provides CSP-style communication between tasks. A producer 
> sends values into a channel; a consumer receives them. The channel handles 
> synchronization and optional buffering — no shared mutable state needed. 
> Channels support unbuffered   
>   (rendezvous, {{create()}}) and buffered ({{create\(n)}}) modes. Sending 
> blocks when the buffer is full; receiving blocks when empty. Since channels 
> implement {{Iterable}}, they work with {{for await}}, regular {{for}} loops, 
> and Groovy collection methods.
>                                                                               
>                                                                               
>                                                                               
>                       
>   h3. Structured Concurrency                                                  
>                                                                               
>                                                                               
>                       
>    
>   {{AsyncScope}} binds the lifetime of child tasks to a scope. When the scope 
> exits, all children are guaranteed complete (or cancelled). This prevents 
> orphaned tasks and silent failures. By default, the scope uses fail-fast 
> semantics — if any child fails,
>    all siblings are cancelled immediately. On JDK 25+, scope tracking uses 
> {{ScopedValue}} for optimal virtual thread performance; on JDK 17–24, a 
> {{ThreadLocal}} fallback is used transparently.
>                                                                               
>                                                                               
>                                                                               
>                       
>   h3. Defer (Go-Style Cleanup)                              
>   The {{defer}} keyword schedules cleanup actions that execute in LIFO order 
> when the enclosing async closure returns, regardless of success or failure. 
> If multiple deferred blocks throw, the first exception is primary and 
> subsequent ones are attached via 
>   {{addSuppressed()}}. If a deferred action returns an {{Awaitable}} or 
> {{Future}}, the result is awaited before the next deferred action runs, 
> ensuring orderly cleanup of asynchronous resources. 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}}, or any custom async 
> type — a single {{await}} keyword, regardless of the underlying library. 
> Drop-in adapter modules are provided for:         
>   - groovy-reactor — {{await}} on {{Mono}}, {{for await}} over {{Flux}}       
>                                                                               
>                                                                               
>                       
>   - groovy-rxjava — {{await}} on {{Single}}/{{Maybe}}/{{Completable}}, {{for 
> await}} over {{Observable}}/{{Flowable}}                                      
>                                                                               
>                        
>                                                                               
>                                                                               
>                                                                               
>                       
>   h2. Thread Safety Mechanisms                                                
>                                                                               
>                                                                               
>                       
>                                                             
>   All concurrency control is internal and transparent to users:
>   - Lock-free synchronization — {{volatile}} fields, {{AtomicInteger}}, 
> {{AtomicReference}}, {{CopyOnWriteArrayList}} used throughout; no 
> {{synchronized}} blocks in the async runtime
>   - TOCTOU prevention — {{GeneratorBridge.yield()}} sets {{producerThread}} 
> before checking the {{closed}} flag, then re-checks after blocking 
> operations, closing a race window with concurrent {{close()}}                 
>                                    
>   - Cooperative cancellation — {{GeneratorBridge.close()}} atomically sets a 
> closed flag, drains any pending handoff, and interrupts the producer thread   
>                                                  
>   - Idempotent close — All close operations are safe to call multiple times 
> from any thread                                                               
>                                                                               
>                         
>                                                                               
>                                                                               
>                                                                               
>                       
>   h2. Cross-Language Comparison                                               
>                                                                               
>                                                                               
>                       
>   ||Aspect||Groovy||JavaScript||C#||Kotlin||Swift||                           
>                                                                               
>                                                                               
>                       
>   |Async declaration|async \{ ... \}|{{async function foo()}}|{{async Task 
> 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}}|                  
>                                                                               
>                                                                               
>                       
>   |Channels|{{AsyncChannel}}|(none)|{{Channel}}|{{Channel}}|{{AsyncStream}} 
> (limited)|                                                                    
>                                                                               
>                         
>   |Structured 
> concurrency|{{AsyncScope}}|(none)|(none)|{{coroutineScope}}|{{TaskGroup}}|    
>                                                                               
>                                                                               
>         
>   |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