Pages

Wednesday, March 26, 2014

Async

Async 

Table of Contents 

  • async and await
  • Type Annotating Async Functions
  • Example: Coalesced Fetching
  • Signature Examples
  • Awaitables vs Continuations
Warning
We felt it would be useful to introduce the concept and technology of async in order to get developers used to the syntax and some of the technical details. For example, you can currently write basic async functions that call other async functions. However, we are currently finalizing other foundations (e.g. async database, scheduling, and memory handling APIs) which will be required to reach the full potential of async in production.
Asynchronous programming refers to a programming design pattern that allows several distinct tasks to cooperatively transfer control to one another on a given thread of execution. The tasks are isolated from one another from the perspective of dependency minimization and task interaction. Asynchronous programming is most often used in the context of input/output (I/O). For synchronous (i.e., blocking) I/O APIs, asynchronous tasks can be batched together to perform a set of work. And, of course, asynchronous (i.e., non-blocking) I/O APIs fit nicely into the asynchronous programming model.
To enable asynchronous programming in HHVM, the concept of creating async functions was used. The two HHVM PHP language keywords that enable async functions are async and await. async declares a function as asynchronous.await suspends the execution of an async function until the result of the asynchronous operation represented by awaitis available. The return value of a function that await can be used upon is an object that implements Awaitable<T>.
<?hh
class Foo{}
class 
Bar {
  public function 
getFoo(): Foo {
    return new 
Foo();
  }
}
async function gen_foo(int $a): Awaitable<?Foo> {
  if (
$a === 0) {
    return 
null;
  }

  
$bar await gen_bar($a);
  if (
$bar !== null) {
    return 
$bar->getFoo();
  }

  return 
null;
}
async function gen_bar(int $a): Awaitable<?Bar> {
  if (
$a === 0) {
    return 
null;
  }

  return new 
Bar();
}

gen_foo(4);
gen_foo() is an async function as shown by the async keyword preceding the function signature. Async functions always returns an object that implements Awaitable<T> (the normal concrete implementation is WaitHandle<T>, but it is almost always preferred to use the Awaitable<T> interface).
The call to gen_foo() brings with it some interesting properties that are unique to async functions. The async function may eagerly execute part of the async function body. The call gen_bar() first returns an Awaitable, that may or may not be finished in its execution. If it is not finished, gen_foo() suspends execution; otherwise gen_foo() just unpacks the result and continues eager execution. The execution will not suspend outside of the await statement. The asynchronous programming framework keeps track of all of the asynchronous operations that should be completed.

async and await 

Warning
We felt it would be useful to introduce the concept and technology of async in order to get developers used to the syntax and some of the technical details. For example, you can currently write basic async functions that call other async functions. However, we are currently finalizing other foundations (e.g. async database, scheduling, and memory handling APIs) which will be required to reach the full potential of async in production.
async declares a function as asynchronous. await suspends the execution of an async function until the result of the asynchronous operation represented by await is available. The return value of a function that await can be used upon is an object that implements Awaitable<T>.

Type Annotating Async Functions 

Warning
We felt it would be useful to introduce the concept and technology of async in order to get developers used to the syntax and some of the technical details. For example, you can currently write basic async functions that call other async functions. However, we are currently finalizing other foundations (e.g. async database, scheduling, and memory handling APIs) which will be required to reach the full potential of async in production.
Typing async functions so that the Hack type checker will understand them is fairly straightforward. Just ensure that the function signature is preceded by the async keyword and that the return type is an object that implementsAwaitable<T> (normally this should just be Awaitable<T> directly).
If an implementation of an async function returns type T, the return type visible to its callers is Awaitable<T>.

Example: Coalesced Fetching 

Warning
We felt it would be useful to introduce the concept and technology of async in order to get developers used to the syntax and some of the technical details. For example, you can currently write basic async functions that call other async functions. However, we are currently finalizing other foundations (e.g. async database, scheduling, and memory handling APIs) which will be required to reach the full potential of async in production.
Async provides an interesting mechanism to perform coalesced fetching. Let's take ids as the "things" we want to fetch. In essence, your code is written as if you are fetching one ID, but, under the covers, the query is being batched.
<?hh
class Batcher {
  private static ?
Awaitable<array<intint>> $pendingWH null;
  private static array<
intint$ids = array();

  public static 
async function fetch(int $id): Awaitable<int> {
    
self::$ids[$id] = $id;
    if (
self::$pendingWH === null) {
      
self::$pendingWH self::fetchDispatch();
    }
    
$results await self::$pendingWH;
    return 
$results[$id];
  }

  private static 
async function dispatch(): Awaitable<array<intint>> {
    
await RescheduleWaitHandle::create(00);
    
$ids self::$ids;
    
self::$ids null;
    
self::$pendingWH null;

    
// do expensive serial multi-fetch
    
echo "Fetch ".count($ids)." ids:\n";
    
$results array_map($id ==> $id $id$ids);
    
var_dump($results);

    return 
$results;
  }
}
async function gen1(): Awaitable<T> {
  
$r await Batcher::fetch(1);
  echo "
Got result for id 1: $r\n";
  
$r await Batcher::fetch(2);
  echo "
Got result for id 2: $r\n";
}
async function gen2(): Awaitable<T> {
  
$r await Batcher::fetch(3);
  echo "
Got result for id 3: $r\n";
}
async function run(): Awaitable<T> {
  
await GenArrayWaitHandle::create(array(gen1(), gen2()));
}
run()->join();

Signature Examples 

Warning
We felt it would be useful to introduce the concept and technology of async in order to get developers used to the syntax and some of the technical details. For example, you can currently write basic async functions that call other async functions. However, we are currently finalizing other foundations (e.g. async database, scheduling, and memory handling APIs) which will be required to reach the full potential of async in production.
<?hh
async 
function genFoo(): Awaitable<Foo> { return new Foo(); }async function cached_result<T>(T $x): Awaitable<T> { return $x; }async function gen_void(): Awaitable<void> { return; }async function gen_add(Awaitable<int$genAAwaitable<int$genB): Awaitable<int> { 
  list(
$a$b) = await genva($genA$genB); 
  return 
$a $b
}
class 
Preparable<T> implements Awaitable<T> { ... }
class 
MyPreparable extends Preparable<MyPreparable> { ... }


Awaitables vs Continuations 

Warning
We felt it would be useful to introduce the concept and technology of async in order to get developers used to the syntax and some of the technical details. For example, you can currently write basic async functions that call other async functions. However, we are currently finalizing other foundations (e.g. async database, scheduling, and memory handling APIs) which will be required to reach the full potential of async in production.
This table briefly summarizes Continuation<T> and Awaitable<T>. Continuations are used in *synchronous, generator* based programming on functions that yield results.
Type
Definition
How to Use
Notes
Continuation<T>
The interface for items that are generators. They can be looped over.
yield directly (e.g.,yield $foo;)
Generators must always yield the same type. Continuations yield items of a type T. Continuations are used only with yield.
Awaitable<T>
The interface for items that are returned asynchronously.
Awaitables are used in function declared as async and on functions that can be "awaited" upon via the asynckeyword.
Only use Awaitables with async functions; Continuations should not be used for this purpose.



1 comment:

  1. ceramic vs titanium curling iron - Titanium Art
    Titanium's titanium lug nuts bronze designs are just as ornate as the titanium glasses frames red. For titanium flashlight those who enjoy a good titanium bikes balance of heat and light, TITONI's premium ceramic art gold titanium alloy

    ReplyDelete