# AMPHP v3 — Cancellation Patterns Always accept `?Cancellation` in functions that do I/O. The caller decides the timeout policy. --- ## TimeoutCancellation ```php request(new Request($url), $cancellation); return $response->getBody()->buffer(); } catch (CancelledException $e) { throw $e; // let caller handle it } } // Caller passes the timeout policy: $result = fetchData('https://api.example.com', new TimeoutCancellation(5.0)); ``` --- ## DeferredCancellation — manual cancel ```php getCancellation()); return 'completed'; } catch (CancelledException) { return 'manually-cancelled'; } }); delay(0.1); // let it start $dc->cancel(); // cancel from another fiber echo $future->await(); // 'manually-cancelled' ``` --- ## CompositeCancellation — first wins ```php getCancellation(), new TimeoutCancellation(30.0), ); try { delay(100.0, cancellation: $cancellation); } catch (CancelledException) { echo "Cancelled\n"; } ``` --- ## Cooperative cancellation check in a loop ```php throwIfRequested(); // check before each item $results[] = process($item); } return $results; } $result = processItems($bigList, new TimeoutCancellation(2.0)); ``` --- ## Subscribing to cancellation for cleanup ```php getCancellation(); // Register cleanup callback $id = $cancellation->subscribe(function (): void { releaseResource(); // runs when cancelled }); $future = async(function () use ($cancellation): void { try { delay(10.0, cancellation: $cancellation); } catch (CancelledException) { // cleanup subscription is triggered automatically } }); delay(0.01); $dc->cancel(); $future->await(); $cancellation->unsubscribe($id); // deregister when no longer needed ``` --- ## Key Facts - `TimeoutCancellation(float $seconds)` — cancel after N seconds - `DeferredCancellation` — cancel manually via `->cancel()`; get token via `->getCancellation()` - `CompositeCancellation(...$cancellations)` — cancelled when **any** source fires - `NullCancellation` — no-op, useful as default `?Cancellation` argument - Cancellation is **advisory** — operations may complete anyway (e.g. nearly-finished HTTP request) - Always let `CancelledException` propagate unless you specifically need to suppress it - `delay()` uses a **named** `cancellation:` parameter: `delay(5.0, cancellation: $token)`