protect
(PHP 8.6+, True Async 1.0)
protect() — Esegue una closure in modalità non annullabile. L’annullamento della coroutine viene posticipato fino al completamento della closure.
Descrizione
protect(\Closure $closure): mixed
Mentre $closure è in esecuzione, la coroutine è contrassegnata come protetta. Se una richiesta di annullamento arriva durante questo periodo, AsyncCancellation verrà lanciata solo dopo il completamento della closure.
Parametri
closure
Una closure da eseguire senza interruzione da annullamento.
Valori di ritorno
Restituisce il valore restituito dalla closure.
Esempi
Esempio #1 Protezione di una transazione
<?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;
});
// Se la coroutine è stata annullata durante protect(),
// AsyncCancellation verrà lanciata qui — dopo il commit()
?>
Esempio #2 Protezione della scrittura su file
<?php
use function Async\protect;
protect(function() {
$fp = fopen('data.json', 'w');
fwrite($fp, json_encode($data));
fclose($fp);
});
?>
Esempio #3 Ottenere un risultato
<?php
use function Async\protect;
$cached = protect(function() use ($cache, $key) {
$value = computeExpensiveResult();
$cache->set($key, $value);
return $value;
});
?>
Esempio #4 Annullamento posticipato e diagnostica
Durante protect(), l’annullamento viene salvato ma non applicato. Questo può essere verificato tramite i metodi della coroutine:
<?php
use function Async\spawn;
use function Async\protect;
use function Async\current_coroutine;
$coroutine = spawn(function() {
protect(function() {
$me = current_coroutine();
// All'interno di protect() dopo cancel():
echo $me->isCancellationRequested() ? "true" : "false"; // true
echo "\n";
echo $me->isCancelled() ? "true" : "false"; // false
echo "\n";
suspend();
echo "Operazione protetta completata\n";
});
// AsyncCancellation viene lanciata qui — dopo protect()
echo "Questo codice non verrà eseguito\n";
});
suspend(); // Lascia che la coroutine entri in protect()
$coroutine->cancel();
suspend(); // Lascia che protect() termini
echo $coroutine->isCancelled() ? "true" : "false"; // true
?>
isCancellationRequested()—trueimmediatamente dopocancel(), anche all’interno diprotect()isCancelled()—falsementreprotect()è in esecuzione, poitrue
Note
Nota: Se l’annullamento è avvenuto durante
protect(),AsyncCancellationverrà lanciata immediatamente dopo il ritorno della closure — il valore di ritorno diprotect()andrà perso in questo caso.
Nota:
protect()non rende la closure atomica — altre coroutine possono essere eseguite durante le operazioni di I/O al suo interno.protect()garantisce solo che l’annullamento non interromperà l’esecuzione.
Vedi anche
- Cancellazione — meccanismo di annullamento cooperativo
- suspend() — sospensione di una coroutine