Класс parallel\Runtime

(0.8.0)

Объекты во временя выполнения

Каждая среда выполнения представляет собой один поток PHP, поток создаётся (и загружается) при создании. Затем поток ожидает, пока задачи будут запланированы: запланированные задачи будут выполняться FIFO, а затем поток возобновит ожидание, пока не будут запланированы другие задачи или пока он не будет закрыт, убит или уничтожен в соответствии с обычными правилами области видимости объектов PHP.

Внимание

Когда среда выполнения уничтожается обычными правилами области видимости объектов PHP, она сначала выполняет все запланированные задачи и при этом блокирует добавление новых.

Начальная загрузка во время выполнения

Когда создаётся новая среда выполнения, она не разделяет код с потоком (или процессом), который её создал. Это означает, что в нём не загружены те же классы и функции, а также не установлен один и тот же автозагрузчик. В некоторых случаях желательна очень лёгкая среда выполнения, потому что задачи, которые будут запланированы, не нуждаются в доступе к коду в родительском потоке. В тех случаях, когда задачам нужен доступ к одному и тому же коду, достаточно установить автозагрузчик в качестве начальной загрузки.

Замечание:

Предварительная загрузка может использоваться вместе с параллельной, в этом случае предварительно загруженный код доступен без начальной загрузки.

Обзор класса

final class parallel\Runtime {
/* Создание */
public __construct()
public __construct(string $bootstrap)
/* Выполнение */
public run(Closure $task): ?Future
public run(Closure $task, array $argv): ?Future
/* Присоединение */
public close(): void
public kill(): void
}

Содержание

Добавить

Примечания пользователей 4 notes

up
20
Luciano Vettoretti
6 years ago
basic-multithreading-test.php

<?php
use parallel\Runtime;
use parallel\Channel;

$test = "this var is not accesible in a thread";

// this function will be the threads
$thread_function = function (int $id, Channel $ch) {
    // delay the first thread to simulate better multithreading
    // second thread always finishes first
    $sleep = ($id == 2) ? 1 : 2;
    sleep($sleep);

    // print thread id
    // so it's clear second thread goes first
    // and also you can make sure multithreading is working
    var_dump("thread $id sleep $sleep");

    // try to capture globals, but it's not possible
    echo '$GLOBALS["test"] = ';
    @var_dump($GLOBALS["test"]);

    // the only way to share data is between channels
    $ch->send($sleep);
};

try {
    // each runtime represents a thread
    $r1 = new Runtime();
    $r2 = new Runtime();

    // channel where the date will be sharead
    $ch1 = new Channel();

    // args that will be sent to $thread_function
    $args = array();
    $args[0] = null;
    $args[1] = $ch1;

    // running thread 1
    $args[0] = 1;
    $r1->run($thread_function, $args);

    // running thread 2
    $args[0] = 2;
    $r2->run($thread_function, $args);

    // receive data from channel
    $x = $ch1->recv();
    $y = $ch1->recv();

    // close channel
    $ch1->close();

    echo "\nData received by the channel: $x and $y";
} catch (Error $err) {
    echo "\nError:", $err->getMessage();
} catch (Exception $e) {
    echo "\nException:", $e->getMessage();
}
up
5
gam6itko
4 years ago
<?php

// make sure that is really parallel execution (showcase2).
// Then you use echo within task-function there is a real chance that the application will hang.
// We should control Futures to avoid this behaviour.
// You will get different output on each execution.

use parallel\{Future, Runtime};

const THREADS_COUNT = 10;
const THREADS_I_MAX = 100;

// executed within thread
$task = static function (int $i, int $to): void {
    echo "[enter$i]";
    for ($j = 0; $j < $to; $j++) {
        echo $i;
    }
    echo "[exit$i]";
};

// creating a few threads
$runtimeList = [];
for ($i = 0; $i < THREADS_COUNT; $i++) {
    $runtimeList[] = new Runtime();
}
// run all threads
$futureList = [];
foreach ($runtimeList as $i => $runtime) {
    echo "[run$i]";
    $futureList[] = $runtime->run($task, [$i, THREADS_I_MAX]);
}

// waiting until all threads are done
// if you delete code bellow then your script will hang
do {
    usleep(1);
    $allDone = array_reduce(
        $futureList,
        function (bool $c, Future $future): bool {
            return $c && $future->done();
        },
        true
    );
} while (false === $allDone);
echo "done\n";
up
0
Mikhail Streltsov (admin at my-fantasy dot ru)
2 years ago
new Runtime()  will reset some basic (before number 10+-) Linux signal. 

If you already set handle of signal by pcntl_signal function - you need do it again
up
0
gam6itko
4 years ago
<?php

// make sure that is really parallel execution
// you will get different output on each script run

use parallel\{Channel, Runtime};

const THREADS_COUNT = 5;
const THREADS_I_MAX = 10;

$ch = new Channel();

// executed within thread
$task = static function (Channel $ch, int $i, int $to): void {
    echo "[enter: $i]\n";
    for ($j = 0; $j < $to; $j++) {
        $ch->send($i);
    }
    echo "[exit: $i]\n";
};

// creating a few threads
$runtimeList = [];
for ($i = 0; $i < THREADS_COUNT; $i++) {
    $runtimeList[] = new Runtime();
}
// run all threads
foreach ($runtimeList as $i => $runtime) {
    echo "[run: $i]\n";
    $runtime->run($task, [$ch, $i, THREADS_I_MAX]);
}

// reading messages from channel
$queue = '';
for ($i = 0; $i < THREADS_COUNT * THREADS_I_MAX; $i++) {
    $queue .= $ch->recv();
}
$ch->close();

echo $queue . PHP_EOL;
To Top