Amp harnesses Promises [another name for Awaitables] and Generators for coroutine creation.

require __DIR__ . '/vendor/autoload.php';

use Amp\\Dns;

// Try our system defined resolver or googles, whichever is fastest
function queryStackOverflow($recordtype) {
    $requests = [
        Dns\\query("stackoverflow.com", $recordtype),
        Dns\\query("stackoverflow.com", $recordtype, ["server" => "8.8.8.8"]),
    ];
    // returns a Promise resolving when the first one of the requests resolves
    return yield Amp\\first($request);
}

\\Amp\\run(function() { // main loop, implicitly a coroutine
    try {
        // convert to coroutine with Amp\\resolve()
        $promise = Amp\\resolve(queryStackOverflow(Dns\\Record::NS));
        list($ns, $type, $ttl) = // we need only one NS result, not all
            current(yield Amp\\timeout($promise, 2000 /* milliseconds */));
        echo "The result of the fastest server to reply to our query was $ns";
    } catch (Amp\\TimeoutException $e) {
        echo "We've heard no answer for 2 seconds! Bye!";
    } catch (Dns\\NoRecordException $e) {
        echo "No NS records there? Stupid DNS nameserver!";
    }
});