Asynchronous Programming
ESUG 2024, Lille, France
James Foster
Agenda
u Asynchronous Programming and Synchronization
u Exploring Other Languages
u Exploring Smalltalk Implementations
u Observations
u Questions
Asynchronous Programming and
Synchronization
Futures and Promises
Synchronous: Blocking
u Blocking & Sequential
Asynchronous:
Nonblocking and Parallel
u Blocking & Sequential u Nonblocking & Parallel
Fork
Asynchronous:
Nonblocking and Concurrent
u Blocking & Sequential u Nonblocking & Parallel
Fork
u Nonblocking & Concurrent
Fork
Synchronization
u Coordinating multiple processes to join up.
Fork
Join
Web Server
Asynchronous Programming in GemStone
u Demo of WebGS with parallel sessions
Futures and Promises
u "In computer science, future, promise, delay,
and deferred refer to constructs used for synchronizing
program execution in some concurrent programming
languages. They describe an object that acts as a proxy
for a result that is initially unknown, usually because
the computation of its value is not yet complete."
u — https://en.wikipedia.org/wiki/Futures_and_promises
Exploring Other Languages
Futures and Promises
JavaScript: Promises
u A Promise is in one of these states:
u Pending: Initial state, neither fulfilled nor rejected.
u Fulfilled: The operation completed successfully.
u Rejected: The operation failed.
JavaScript: Example
let promise = new Promise(function(resolve, reject) {
// Asynchronous operation here
if (/* operation successful */) {
resolve(value); // Resolve with a value
} else {
reject(error); // Reject with an error
}
});
promise.then(
function(value) { /* handle a successful operation */ },
function(error) { /* handle an error */ }
);
JavaScript: Summary
• Creating a Promise: The Promise constructor is used to create a promise. It
takes a function (executor) that should start an asynchronous operation and
eventually call either the resolve (to indicate success) or reject (to indicate
failure) function to settle the promise.
• Consuming a Promise: The .then() method is used to attach callbacks to
handle the fulfillment or rejection of the promise. The .catch() method is used
to handle rejection, and .finally() method allows you to execute logic
regardless of the promise's outcome.
• Chaining Promises: Promises can be chained to perform a series of
asynchronous operations in sequence. Each .then() returns a new promise,
allowing for further methods to be called in sequence.
JavaScript: Conclusion
u Promises are a core part of asynchronous programming in
JavaScript, making it easier to work with asynchronous
operations by avoiding the complexity of nested callbacks,
known as "callback hell."
Python: ThreadPoolExecutor
from concurrent.futures import ThreadPoolExecutor, as_completed
def task(n):
return n + 1
# Create a ThreadPoolExecutor
with ThreadPoolExecutor(max_workers=5) as executor:
# Submit tasks to the executor
futures = [executor.submit(task, i) for i in range(5)]
# Wait for the futures to complete and get their results
for future in as_completed(futures):
print(future.result())
Python: asyncio.Future
import asyncio
async def set_after(fut, delay, value):
# Wait
await asyncio.sleep(delay)
# Set the result
fut.set_result(value)
async def main():
# Create a Future object
fut = asyncio.Future()
# Schedule the future
await set_after(fut, 1, 'hello!')
# Wait for the future
print(await fut)
asyncio.run(main())
Java: CompletableFuture
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// Create a CompletableFuture
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
// Simulate a long-running job
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Hello";
});
// Chain a computation stage
CompletableFuture<String> greetingFuture =
future.thenApply(result -> result + ", World!");
// Block and get the result
System.out.println(greetingFuture.get()); // Prints "Hello, World!" after 1 second
}
}
Dart: async and await
u A long running method is (should be!) annotated with async.
u An async method returns a Future.
u A callback may be added to a Future to handle:
u A normal result; or,
u An error.
u Instead of adding a callback, you can await for a Future to complete.
u This will block, so should not be done in the primary (UI) thread.
u In background threads this allows synchronous (linear) code.
import 'dart:async';
Future<String> fetchUserOrder() async {
// Simulate a network request to fetch a user order
await Future.delayed(Duration(seconds: 2));
return 'Cappuccino';
}
void main() async {
print('Fetching user order...');
try {
// Wait for the Future to complete and extract its result
String order = await fetchUserOrder();
print('Your order is: $order');
} catch (err) {
print('Failed to fetch user order: $err');
}
}
Exploring Smalltalk Implementations
Not exhaustive!
VAST Platform
u Modeled on Dart
u Demo
Pharo
u Semaphore approach
u TaskIt package
u Demo
Glamorous Toolkit
u Documentation
Observations
u Application developers
u Avoid long-running (blocking) tasks in the UI thread.
u Futures/Promises simplify the handling of asynchronous tasks.
u Library developers
u Use Futures/Promises for long-running operations (disk, network, etc.)
u Force application developers to use Futures!
Questions?
u James.Foster@GemTalkSystems.com
u VP of Finance and Operations, GemTalk Systems LLC
u James.Foster@WallaWalla.edu
u Associate Professor of Computer Science, Walla Walla University

Asynchronous Programming. Talk from ESUG2024

  • 1.
    Asynchronous Programming ESUG 2024,Lille, France James Foster
  • 2.
    Agenda u Asynchronous Programmingand Synchronization u Exploring Other Languages u Exploring Smalltalk Implementations u Observations u Questions
  • 3.
  • 4.
  • 5.
    Asynchronous: Nonblocking and Parallel uBlocking & Sequential u Nonblocking & Parallel Fork
  • 6.
    Asynchronous: Nonblocking and Concurrent uBlocking & Sequential u Nonblocking & Parallel Fork u Nonblocking & Concurrent Fork
  • 7.
    Synchronization u Coordinating multipleprocesses to join up. Fork Join
  • 8.
  • 9.
    Asynchronous Programming inGemStone u Demo of WebGS with parallel sessions
  • 10.
    Futures and Promises u"In computer science, future, promise, delay, and deferred refer to constructs used for synchronizing program execution in some concurrent programming languages. They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is not yet complete." u — https://en.wikipedia.org/wiki/Futures_and_promises
  • 11.
  • 12.
    JavaScript: Promises u APromise is in one of these states: u Pending: Initial state, neither fulfilled nor rejected. u Fulfilled: The operation completed successfully. u Rejected: The operation failed.
  • 13.
    JavaScript: Example let promise= new Promise(function(resolve, reject) { // Asynchronous operation here if (/* operation successful */) { resolve(value); // Resolve with a value } else { reject(error); // Reject with an error } }); promise.then( function(value) { /* handle a successful operation */ }, function(error) { /* handle an error */ } );
  • 14.
    JavaScript: Summary • Creatinga Promise: The Promise constructor is used to create a promise. It takes a function (executor) that should start an asynchronous operation and eventually call either the resolve (to indicate success) or reject (to indicate failure) function to settle the promise. • Consuming a Promise: The .then() method is used to attach callbacks to handle the fulfillment or rejection of the promise. The .catch() method is used to handle rejection, and .finally() method allows you to execute logic regardless of the promise's outcome. • Chaining Promises: Promises can be chained to perform a series of asynchronous operations in sequence. Each .then() returns a new promise, allowing for further methods to be called in sequence.
  • 15.
    JavaScript: Conclusion u Promisesare a core part of asynchronous programming in JavaScript, making it easier to work with asynchronous operations by avoiding the complexity of nested callbacks, known as "callback hell."
  • 16.
    Python: ThreadPoolExecutor from concurrent.futuresimport ThreadPoolExecutor, as_completed def task(n): return n + 1 # Create a ThreadPoolExecutor with ThreadPoolExecutor(max_workers=5) as executor: # Submit tasks to the executor futures = [executor.submit(task, i) for i in range(5)] # Wait for the futures to complete and get their results for future in as_completed(futures): print(future.result())
  • 17.
    Python: asyncio.Future import asyncio asyncdef set_after(fut, delay, value): # Wait await asyncio.sleep(delay) # Set the result fut.set_result(value) async def main(): # Create a Future object fut = asyncio.Future() # Schedule the future await set_after(fut, 1, 'hello!') # Wait for the future print(await fut) asyncio.run(main())
  • 18.
  • 19.
    import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; publicclass CompletableFutureExample { public static void main(String[] args) throws ExecutionException, InterruptedException { // Create a CompletableFuture CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { try { // Simulate a long-running job Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return "Hello"; }); // Chain a computation stage CompletableFuture<String> greetingFuture = future.thenApply(result -> result + ", World!"); // Block and get the result System.out.println(greetingFuture.get()); // Prints "Hello, World!" after 1 second } }
  • 20.
    Dart: async andawait u A long running method is (should be!) annotated with async. u An async method returns a Future. u A callback may be added to a Future to handle: u A normal result; or, u An error. u Instead of adding a callback, you can await for a Future to complete. u This will block, so should not be done in the primary (UI) thread. u In background threads this allows synchronous (linear) code.
  • 21.
    import 'dart:async'; Future<String> fetchUserOrder()async { // Simulate a network request to fetch a user order await Future.delayed(Duration(seconds: 2)); return 'Cappuccino'; } void main() async { print('Fetching user order...'); try { // Wait for the Future to complete and extract its result String order = await fetchUserOrder(); print('Your order is: $order'); } catch (err) { print('Failed to fetch user order: $err'); } }
  • 22.
  • 23.
  • 24.
    Pharo u Semaphore approach uTaskIt package u Demo
  • 25.
  • 26.
    Observations u Application developers uAvoid long-running (blocking) tasks in the UI thread. u Futures/Promises simplify the handling of asynchronous tasks. u Library developers u Use Futures/Promises for long-running operations (disk, network, etc.) u Force application developers to use Futures!
  • 27.
    Questions? u James.Foster@GemTalkSystems.com u VPof Finance and Operations, GemTalk Systems LLC u James.Foster@WallaWalla.edu u Associate Professor of Computer Science, Walla Walla University