cancellable<T> function
Awaits work, rejecting early with CancelledException when token
fires first (issue #1923 AC2): the caller stops waiting, but the
underlying work itself is NOT aborted — a paid provider request runs
to completion and its late result or failure is discarded by the race.
A null token just awaits work.
Implementation
Future<T> cancellable<T>(CancelToken? token, Future<T> Function() work) {
if (token == null) return work();
return Future.any<T>([
work(),
token.onCancel.then<T>((_) => throw CancelledException(token.cancelReason)),
]);
}