Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing Futures #145

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Introducing Futures #145

wants to merge 3 commits into from

Conversation

leocavalcante
Copy link
Member

This PR introduces Futures as part of Swoole's standard library features.

Futures are abstractions on top of Coroutines providing alternative syntax for building concurrent programs with Swoole.

Main differences from Coroutines are:

Futures are lazy

They don't evaluate until you call await:

$future = Future\async(static function (): void {
    echo "are lazy\n";
});

Coroutine::create(static function (): void {
    echo 'Futures ';
});

echo $future->await();

Futures can return values

The Channel handling is done under the hood:

$future = Future\async(static function (): string {
    return Http\get('https://httpbin.org/get')->getBody();
});

echo $future->await();

Futures propagates exceptions

$future = Future\async(static function (): string {
    throw new RuntimeException('Futures propagates exceptions');
});

try {
    $future->await();
} catch (Throwable $e) {
    echo $e->getMessage();
}

Futures synchronization is similar

It uses Coroutine::join under the hood:

$future1 = \Swoole\Future::create(static function () {
    return \Swoole\Coroutine\Http\get('https://httpbin.org/delay/2')->getBody();
});

$future2 = \Swoole\Future::create(static function () {
    return \Swoole\Coroutine\Http\get('https://httpbin.org/delay/2')->getBody();
});

echo implode(PHP_EOL, \Swoole\Future::join([$future1, $future2]));

@leocavalcante leocavalcante added enhancement New feature or request rfc Request for comments labels Dec 26, 2021
@leocavalcante leocavalcante self-assigned this Dec 26, 2021
@deminy deminy self-requested a review December 29, 2021 06:33
return new self($func);
}

public static function join(array $futures, float $timeout = -1): array

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your implementation is good and readable. But, I would put some minor tweaks (not functional ones, just a different style and one less variable to decrement) into it:

   public static function join(array $futures, float $timeout = -1): array
    {
        $ch = new Channel(count($futures));

        Coroutine::join(array_map(static function (Future $future) use ($ch): int {
            return $future->run($ch);
        }, $futures));

        $rets = [];
        while ($ret = $ch->pop($timeout)) {
            if ($ret instanceof Throwable) {
                throw $ret;
            }

            $rets[] = $ret;
        }

        return $rets;
    }

@johanjanssens
Copy link

@leocavalcante This is really nice work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request rfc Request for comments
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants