Update README regarding cancellation (#450)
* Update README regarding cancellation * Apply suggestions from code review Co-authored-by: Eugene Kabanov <eugene.kabanov@status.im> --------- Co-authored-by: Jacek Sieka <jacek@status.im> Co-authored-by: Eugene Kabanov <eugene.kabanov@status.im>
This commit is contained in:
parent
f56d286687
commit
12dc36cfee
61
README.md
61
README.md
|
@ -301,45 +301,64 @@ effects on forward declarations, callbacks and methods using
|
|||
|
||||
### Cancellation support
|
||||
|
||||
Any running `Future` can be cancelled. This can be used to launch multiple
|
||||
futures, and wait for one of them to finish, and cancel the rest of them,
|
||||
to add timeout, or to let the user cancel a running task.
|
||||
Any running `Future` can be cancelled. This can be used for timeouts,
|
||||
to let a user cancel a running task, to start multiple futures in parallel
|
||||
and cancel them as soon as one finishes, etc.
|
||||
|
||||
```nim
|
||||
# Simple cancellation
|
||||
let future = sleepAsync(10.minutes)
|
||||
future.cancel()
|
||||
import chronos/apps/http/httpclient
|
||||
|
||||
# Wait for cancellation
|
||||
let future2 = sleepAsync(10.minutes)
|
||||
await future2.cancelAndWait()
|
||||
proc cancellationExample() {.async.} =
|
||||
# Simple cancellation
|
||||
let future = sleepAsync(10.minutes)
|
||||
future.cancelSoon()
|
||||
# `cancelSoon` will not wait for the cancellation
|
||||
# to be finished, so the Future could still be
|
||||
# pending at this point.
|
||||
|
||||
# Race between futures
|
||||
proc retrievePage(uri: string): Future[string] {.async.} =
|
||||
# requires to import uri, chronos/apps/http/httpclient, stew/byteutils
|
||||
# Wait for cancellation
|
||||
let future2 = sleepAsync(10.minutes)
|
||||
await future2.cancelAndWait()
|
||||
# Using `cancelAndWait`, we know that future2 isn't
|
||||
# pending anymore. However, it could have completed
|
||||
# before cancellation happened (in which case, it
|
||||
# will hold a value)
|
||||
|
||||
# Race between futures
|
||||
proc retrievePage(uri: string): Future[string] {.async.} =
|
||||
let httpSession = HttpSessionRef.new()
|
||||
try:
|
||||
resp = await httpSession.fetch(parseUri(uri))
|
||||
result = string.fromBytes(resp.data)
|
||||
let resp = await httpSession.fetch(parseUri(uri))
|
||||
return bytesToString(resp.data)
|
||||
finally:
|
||||
# be sure to always close the session
|
||||
await httpSession.closeWait()
|
||||
# `finally` will run also during cancellation -
|
||||
# `noCancel` ensures that `closeWait` doesn't get cancelled
|
||||
await noCancel(httpSession.closeWait())
|
||||
|
||||
let
|
||||
let
|
||||
futs =
|
||||
@[
|
||||
retrievePage("https://duckduckgo.com/?q=chronos"),
|
||||
retrievePage("https://www.google.fr/search?q=chronos")
|
||||
]
|
||||
|
||||
let finishedFut = await one(futs)
|
||||
for fut in futs:
|
||||
let finishedFut = await one(futs)
|
||||
for fut in futs:
|
||||
if not fut.finished:
|
||||
fut.cancel()
|
||||
echo "Result: ", await finishedFut
|
||||
fut.cancelSoon()
|
||||
echo "Result: ", await finishedFut
|
||||
|
||||
waitFor(cancellationExample())
|
||||
```
|
||||
|
||||
When an `await` is cancelled, it will raise a `CancelledError`:
|
||||
Even if cancellation is initiated, it is not guaranteed that
|
||||
the operation gets cancelled - the future might still be completed
|
||||
or fail depending on the ordering of events and the specifics of
|
||||
the operation.
|
||||
|
||||
If the future indeed gets cancelled, `await` will raise a
|
||||
`CancelledError` as is likely to happen in the following example:
|
||||
```nim
|
||||
proc c1 {.async.} =
|
||||
echo "Before sleep"
|
||||
|
|
Loading…
Reference in New Issue