protect
(PHP 8.6+, True Async 1.0)
protect() — Виконує замикання в режимі без скасування. Скасування корутини відкладається до завершення замикання.
Опис
protect(\Closure $closure): mixed
Поки $closure виконується, корутина позначена як захищена. Якщо запит на скасування надійде протягом цього часу, AsyncCancellation буде викинуто лише після завершення замикання.
Параметри
closure
Замикання, яке потрібно виконати без переривання скасуванням.
Значення, що повертаються
Повертає значення, яке повернуло замикання.
Приклади
Приклад #1 Захист транзакції
<?php
use function Async\protect;
$db->beginTransaction();
$result = protect(function() use ($db) {
$db->exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
$db->exec("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
$db->commit();
return true;
});
// Якщо корутину було скасовано під час protect(),
// AsyncCancellation буде викинуто тут — після commit()
?>
Приклад #2 Захист запису у файл
<?php
use function Async\protect;
protect(function() {
$fp = fopen('data.json', 'w');
fwrite($fp, json_encode($data));
fclose($fp);
});
?>
Приклад #3 Отримання результату
<?php
use function Async\protect;
$cached = protect(function() use ($cache, $key) {
$value = computeExpensiveResult();
$cache->set($key, $value);
return $value;
});
?>
Приклад #4 Відкладене скасування та діагностика
Під час protect() скасування зберігається, але не застосовується. Це можна перевірити через методи корутини:
<?php
use function Async\spawn;
use function Async\protect;
use function Async\current_coroutine;
$coroutine = spawn(function() {
protect(function() {
$me = current_coroutine();
// Усередині protect() після cancel():
echo $me->isCancellationRequested() ? "true" : "false"; // true
echo "\n";
echo $me->isCancelled() ? "true" : "false"; // false
echo "\n";
suspend();
echo "Protected operation completed\n";
});
// AsyncCancellation викидається тут — після protect()
echo "This code will not execute\n";
});
suspend(); // Дозволити корутині увійти в protect()
$coroutine->cancel();
suspend(); // Дозволити protect() завершитися
echo $coroutine->isCancelled() ? "true" : "false"; // true
?>
isCancellationRequested()—trueодразу післяcancel(), навіть усерединіprotect()isCancelled()—falseпокиprotect()виконується, потімtrue
Примітки
Примітка: Якщо скасування відбулося під час
protect(),AsyncCancellationбуде викинуто одразу після повернення замикання — значення, що повертаєтьсяprotect(), у цьому випадку буде втрачено.
Примітка:
protect()не робить замикання атомарним — інші корутини можуть виконуватися під час операцій введення-виведення всередині нього.protect()лише гарантує, що скасування не перерве виконання.
Дивіться також
- Cancellation — кооперативний механізм скасування
- suspend() — призупинення корутини