C The
C language does not support await/async. Some coroutine libraries such as
s_task simulate the keywords await/async with macros. • include • include "s_task.h" constexpr int STACK_SIZE = 64 * 1024 / sizeof(int); // define stack memory for tasks int g_stack_main[STACK_SIZE]; int g_stack0[STACK_SIZE]; int g_stack1[STACK_SIZE]; void sub_task(__async__, void* arg) { int n = (int)(size_t)arg; for (int i = 0; i
C++ In C++, await (named co_await in C++ to emphasise its context in coroutines) has been officially merged into
C++20. Support for it, coroutines, and the keywords such as co_await are available in
GCC and
MSVC compilers while
Clang has partial support. A proper task class, std::execution::task, was introduced in
C++26. To call it, use std::execution::sync_wait(), which returns std::optional>. It is worth noting that std::promise and std::future, although it would seem that they would be awaitable objects, implement none of the machinery required to be returned from coroutines and be awaited using co_await. Programmers must implement a number of public member functions, such as await_ready, await_suspend, and await_resume on the return type in order for the type to be awaited on. Details can be found on cppreference. import std; using std::optional; using std::tuple; using std::execution::task; task add(int a, int b) noexcept { co_return a + b; } task test() { int ret = co_await add(1, 2); std::println("Return {}", ret); co_return ret; } int main(int argc, char* argv[]) { optional>> result = std::execution::sync_wait(test()); std::println("Result: {}", std::get( result.value_or(std::make_tuple(-1))) ); return 0; }
C# In 2012, C# added the async/await pattern in C# with version 5.0, which Microsoft refers to as the task-based asynchronous pattern (TAP). Async methods usually return either void, Task, Task<T>, Async methods that return void are intended for
event handlers; in most cases where a synchronous method would return void, returning Task instead is recommended, as it allows for more intuitive exception handling (note that Task is invalid in C#). Methods that make use of await must be declared with the async keyword. In methods that have a return value of type Task<T>, methods declared with async must have a
return statement of type assignable to T instead of Task<T>; the compiler wraps the value in the Task<T> generic. It is also possible to await methods that have a return type of Task or Task<T> that are declared without async. The following async method downloads data from a URL using await. Because this method issues a task for each URI before requiring completion with the await keyword, the resources can load at the same time instead of waiting for the last resource to finish before starting to load the next. namespace Wikipedia.Examples; using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; public class Example { public async Task SumPageSizesAsync(IEnumerable uris) { HttpClient client = new(); int total = 0; List> loadUriTasks = new(); foreach (Uri uri in uris) { byte[] loadUriTask = client.GetByteArrayAsync(uri); loadUriTasks.Add(loadUriTask); } foreach (Task> loadUriTask in loadUriTasks) { statusText.Text = $"Found {total} bytes ..."; byte[] resourceAsBytes = await loadUriTask; total += resourceAsBytes.Length; } statusText.Text = $"Found {total} bytes total"; return total; } static async Task Main(string[] args) { List uris = new { new Uri("https://en.wikipedia.org"), new Uri("https://www.microsoft.com"), new Uri("https://www.github.com") } int totalBytes = await SumPageSizesAsync(uris); Console.WriteLine($"Total bytes downloaded: {totalbytes}"); } }
F# In 2007, F# added asynchronous workflows with version 2.0. The asynchronous workflows are implemented as CE (
computation expressions). They can be defined without specifying any special context (like async in C#).
F# asynchronous workflows append a bang (!) to keywords to start asynchronous tasks. The following async function downloads data from an URL using an asynchronous workflow: let asyncSumPageSizes (uris: #seq) : Async = async { use httpClient = new HttpClient() let! pages = uris |> Seq.map(httpClient.GetStringAsync >> Async.AwaitTask) |> Async.Parallel return pages |> Seq.fold (fun accumulator current -> current.Length + accumulator) 0 }
Java Java does not have async and await keywords in the language, however it can be emulated using the java.util.concurrent package, such as the class CompletableFuture (introduced in Java 8). Asynchronous programming is later improved in Java 21 with the introduction of virtual threads and structured task scopes. package org.wikipedia.examples; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import static java.util.concurrent.StructuredTaskScope.ShutdownOnFailure; import static java.util.concurrent.StructuredTaskScope.Subtask; public class AsyncExample { public String fetchData() { // Simulate a time-consuming operation (e.g., network request, database query) try { Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return "Data from remote source"; } public CompletableFuture fetchDataAsync() { return CompletableFuture.supplyAsync(() -> fetchData()); } public static void main(String[] args) throws ExecutionException, InterruptedException { AsyncExample example = new AsyncExample(); // Using CompletableFuture (Java 8) System.out.println("Starting asynchronous operation..."); CompletableFuture future = example.fetchDataAsync(); System.out.println("Doing other work..."); // Wait for the result (similar to 'await') String result = future.get(); System.out.printf("Received result: %s%n", result); // Using Virtual Threads (Java 21): ExecutorService extor = Executors.newVirtualThreadPerTaskExecutor(); System.out.println("Starting virtual thread operation..."); Future fut = extor.submit(() -> { return example.fetchData(); }); System.out.println("Doing other work..."); String result = future.get(); System.out.printf("Received result: %s%n", result); extor.shutdown(); // Using StructuredTaskScope (Java 21) try (ShutdownOnFailure scope = new ShutdownOnFailure()) { Subtask dataTask = scope.fork(example::fetchData); System.out.println("Doing other work..."); scope.join(); // wait for all tasks scope.throwIfFailed(); // propagate if any exceptions String result = future.get(); System.out.printf("Received result: %s%n", result); } } }
JavaScript The await operator in JavaScript (and TypeScript) can only be used from inside an async function or at the top level of a
module. If the parameter is a
promise, execution of the async function will resume when the promise is resolved (unless the promise is rejected, in which case an error will be thrown that can be handled with normal JavaScript
exception handling). If the parameter is not a promise, the parameter itself will be returned immediately. Many libraries provide promise objects that can also be used with await, as long as they match the specification for native JavaScript promises. However, promises from the
jQuery library were not Promises/A+ compatible until jQuery 3.0. Below is an example (modified from this article): interface DBResponse { id: string; rev?: string; ok?: boolean; } interface Document { _id: string; _rev?: string; [key: string]: any; } interface Database { post(doc: object): Promise; get(id: string): Promise; } declare const db: Database; async function createNewDoc(): Promise { const response: DBResponse = await db.post({}); const doc: Document = await db.get(response.id); return doc; } async function main(): Promise { try { const doc: Document = await createNewDoc(); console.log(doc); } catch (err: Error) { console.error("Error creating or fetching document:", err); } } main();
Node.js version 8 includes a utility that enables using the standard library callback-based methods as promises.
Perl The Future::AsyncAwait module was the subject of a Perl Foundation grant in September 2018.
Python Python 3.5 (2015) has added support for async/await as described in PEP 492 (written and implemented by
Yury Selivanov). import asyncio async def main() -> None: print("hello") await asyncio.sleep(1) print("world") if __name__ == "__main__": asyncio.run(main())
Rust On November 7, 2019, async/await was released on the stable version of Rust. Async functions in Rust
desugar to plain functions that return values that implement the Future trait. Currently they are implemented with a
finite-state machine. // In the crate's Cargo.toml, we need `futures = "0.3.0"` in the dependencies section, // so we can use the futures crate extern crate futures; // There is no executor currently in the `std` library. use std::future::Future; // This desugars to something like // `fn async_add_one(num: u32) -> impl Future` async fn async_add_one(num: u32) -> u32 { num + 1 } async fn example_task() -> impl Future { let number = async_add_one(5).await; println!("5 + 1 = {}", number); } fn main() { // Creating the Future does not start the execution. let future = example_task(); // The `Future` only executes when we actually poll it, unlike JavaScript. futures::executor::block_on(future); }
Swift Swift 5.5 (2021) added support for async/await as described in SE-0296. func getNumber() async throws -> Int { try await Task.sleep(nanoseconds: 1_000_000_000) return 42 } Task { let first = try await getNumber() let second = try await getNumber() print(first + second) } == Benefits and criticisms ==