| CARVIEW |
Getting Started
Source Code Fundamentals
Expressions And Operators
Introduction
Operator Precedence
Echo
Exit
Invariant
List
New
Subscript
Member Selection
Scope Resolution
Nameof
Incrementing And Decrementing
Error Control
Casting
Await
Type Assertions
Arithmetic
String Concatenation
Bitwise Operators
Logical Operators
Comparisons
Equality
Ternary
Coalesce
Pipe
Assignment
Yield
XHP Attribute Selection
Statements
Functions
Classes
Traits And Interfaces
Arrays And Collections
Types
Built In Types
Generics
Contexts And Capabilities
Reified Generics
Asynchronous Operations
Readonly
Modules
Packages
Attributes
XHP
Silencing Errors
Contributing
Experimental Features
Expression Trees
Memoization Options
Asynchronous Operations: Concurrent
concurrent concurrently awaits all awaits within a concurrent block and it works with await-as-an-expression as well!
Note: concurrent doesn't mean multithreading
Syntax
concurrent {
$x = await x_async();
await void_async();
$sum = await y_async() + await z_async()();
}
$y = $x + $sum;
Order-of-execution
Each of the statements in a concurrent block should be thought of as running concurrently. This means there shouldn't be any dependencies between the statements in a concurrent block.
Similar to await-as-an-expression, concurrent blocks don't provide a guaranteed order-of-execution between expressions being evaluated for any statement in the concurrent block. We guarantee that modifications to locals will happen after all other expressions resolve and will happen in the order in which they would happen outside a concurrent block.
For this example, we provide no guarantee on the execution order of the calls to x(), y_async() and z_async(). The assignments into $result are guaranteed to be well ordered however.
$result = vec[];
concurrent {
$result[] = x() + await y_async();
$result[] = await z_async();
}
Exceptions
If any statement in a concurrent block throws, there are no guarantees about which (if any) awaited values were assigned or which exception will be propagated if more than one of them threw. For example if you have:
$x = 0;
try {
concurrent {
$x = await async { return 1; };
await async { throw new Exception('foo'); };
await async { throw new Exception('bar'); };
}
} catch (Exception $e) {
var_dump($x, $e->getMessage());
}
Then it is explicitly undefined whether var_dump will see $x === 0 or $x === 1 and whether the message will be 'foo' or 'bar'.
If you need granular exception handling, consider using nested try-catch blocks inside the concurrent block:
concurrent {
$x = await async {
try {
...
return <success path>;
} catch (...) {
return <fallback>;
}
};
$y = await async {
// same here
};
}