structio/tests/self_cancel.py

69 lines
2.2 KiB
Python

import structio
async def sleeper(n):
print(f"[sleeper] Going to sleep for {n} seconds!")
i = structio.clock()
try:
await structio.sleep(n)
except structio.Cancelled:
print(
f"[sleeper] Oh no, I've been cancelled! (was gonna sleep {structio.clock() - i:.2f} more seconds)"
)
raise
print("[sleeper] Woke up!")
async def main_simple(n, o, p):
print(f"[main] Parent is alive, spawning {o} children sleeping {n} seconds each")
t = structio.clock()
async with structio.create_pool() as pool:
for i in range(o):
pool.spawn(sleeper, n)
print(f"[main] Children spawned, sleeping {p} seconds before cancelling")
await structio.sleep(p)
# Note that cancellations propagate to all inner task scopes!
pool.scope.cancel()
print(f"[main] Parent exited in {structio.clock() - t:.2f} seconds")
async def main_nested(n, o, p):
print(
f"[main] Parent is alive, spawning {o} children in two contexts sleeping {n} seconds each"
)
t = structio.clock()
async with structio.create_pool() as p1:
for i in range(o):
p1.spawn(sleeper, n)
async with structio.create_pool() as p2:
for i in range(o):
p2.spawn(sleeper, n)
print(f"[main] Children spawned, sleeping {p} seconds before cancelling")
await structio.sleep(p)
# Note that cancellations propagate to all inner task scopes!
p1.scope.cancel()
print(f"[main] Parent exited in {structio.clock() - t:.2f} seconds")
async def child(scope: structio.TaskScope, x: float):
print(f"[main] Child is alive! Canceling scope in {x} seconds")
await structio.sleep(x)
scope.cancel()
async def main_child(x: float):
print("[main] Parent is alive")
t = structio.clock()
async with structio.create_pool() as p:
print("[main] Spawning child")
p.spawn(child, p.scope, x / 2)
print(f"[main] Child spawned, sleeping for {x} seconds")
await structio.sleep(x)
print(f"[main] Done in {structio.clock() - t:.2f} seconds")
# Should take about 5 seconds
structio.run(main_simple, 5, 2, 2)
structio.run(main_nested, 5, 2, 2)
structio.run(main_child, 2)