ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

Nim Async Task Cancellation with Timeout

Nim

Goal -- WPM

Ready
Exercise Algorithm Area
1import asyncio
2import times
3
4proc simulateLongOperation(durationMs: int): Future[string] =
5let startTime = now_ms()
6let task = async:
7sleep(durationMs)
8let elapsedTime = now_ms() - startTime
9if elapsedTime < durationMs:
10# This case should ideally not happen with sleep, but good for robustness
11raise newException(ValueError, "Operation completed too quickly!")
12result = "Operation completed successfully in " & $elapsedTime & "ms."
13return task
14
15proc runWithTimeout(operation: Future[string], timeoutMs: int): Future[string] =
16let timeoutTask = async:
17sleep(timeoutMs)
18raise newException(TimeoutError, "Operation timed out after " & $timeoutMs & "ms.")
19
20# Use select to race the operation against the timeout
21let winner = select(operation, timeoutTask)
22
23# If the timeout task won, we need to cancel the operation task
24if winner == timeoutTask:
25# Note: In Nim, cancelling a Future directly isn't always straightforward
26# and depends on how the Future is implemented. For this example,
27# we rely on the fact that the timeoutFuture will raise, effectively
28# stopping further progress on the operation if it hasn't finished.
29# A more explicit cancellation mechanism might involve passing a cancel token.
30discard
31
32return winner
33
34proc main() =
35echo "Starting operation with 500ms duration and 1000ms timeout..."
36try:
37let result1 = await runWithTimeout(simulateLongOperation(500), 1000)
38echo "Result 1: ", result1
39except TimeoutError as e:
40echo "Error 1: ", e.msg
41except Exception as e:
42echo "Unexpected error 1: ", e.msg
43
44echo "\nStarting operation with 1500ms duration and 1000ms timeout..."
45try:
46let result2 = await runWithTimeout(simulateLongOperation(1500), 1000)
47echo "Result 2: ", result2
48except TimeoutError as e:
49echo "Error 2: ", e.msg
50except Exception as e:
51echo "Unexpected error 2: ", e.msg
52
53echo "\nStarting operation with 200ms duration and 1000ms timeout..."
54try:
55let result3 = await runWithTimeout(simulateLongOperation(200), 1000)
56echo "Result 3: ", result3
57except TimeoutError as e:
58echo "Error 3: ", e.msg
59except Exception as e:
60echo "Unexpected error 3: ", e.msg
61
62when isMainModule:
63asyncCheck main()
Algorithm description viewbox

Nim Async Task Cancellation with Timeout

Algorithm description:

This Nim code demonstrates asynchronous task management with timeouts using the `asyncio` module. The `simulateLongOperation` function represents a task that takes time to complete, while `runWithTimeout` races this task against a timer. If the operation doesn't complete within the specified timeout, a `TimeoutError` is raised. This pattern is crucial for preventing applications from hanging indefinitely on unresponsive operations.

Algorithm explanation:

The `simulateLongOperation` procedure simulates a time-consuming task by sleeping for a given duration and returning a success message. The `runWithTimeout` procedure is the core of the example; it uses `asyncio.select` to concurrently run the `operation` Future and a `timeoutTask` Future. The `timeoutTask` is designed to raise a `TimeoutError` after a specified `timeoutMs`. `select` returns the result of whichever Future completes first. If `timeoutTask` wins, a `TimeoutError` is propagated. If `operation` wins, its result is returned. This pattern ensures that no asynchronous operation blocks the event loop indefinitely. The time complexity for the operation itself is dependent on the `durationMs`, but the `runWithTimeout` mechanism adds a constant overhead for setting up the futures and the `select` operation. Space complexity is O(1) for managing the futures and the event loop state.

Pseudocode:

Async procedure simulateLongOperation(duration):
  Start timer
  Sleep for duration
  Stop timer
  Return success message with elapsed time

Async procedure runWithTimeout(operation, timeout):
  Create a timeoutTask that raises TimeoutError after timeout duration
  Race operation and timeoutTask using select
  If timeoutTask finished first:
    Propagate TimeoutError
  Else (operation finished first):
    Return operation's result