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
?>

Note

Nota: Se l’annullamento è avvenuto durante protect(), AsyncCancellation verrà lanciata immediatamente dopo il ritorno della closure — il valore di ritorno di protect() 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