How to access the "current run’s clock"

Hello!

I have a nursery that I want to cancel at t + 2, where t is only known somewhere in the nursery.

Here’s what it should be doing:

async with trio.open_nursery() as nursery:
    run_scene(nursery) # exits when the scene finishes
    nursery.cancel_scope.deadline += now() + 2

Notice how run_scene is sync: all it can do is start_soon tasks. I want to give the tasks that run_scene spawned at most 2 seconds to close, once it run_scene has exited. I can’t cancel straight away because
the async close tasks (whatever they are) have been start_soon, not awaited.

But there’s no now() function. Looking at the documentation for move_on_at, I’m not even sure that I understand how to use it.

cancel_scope.deadline: An absolute time on the current run’s clock at which this scope will automatically become cancelled.

How can we know the internal time of the clock?

I looked at the source code of move_on_after, because it has to use this now() function, and it uses _core!

https://github.com/python-trio/trio/blob/master/trio/_timeouts.py#L42

Is there an other way to access the internal time? Because I should be able to use every regular function like move_on_after without using _core, right?

1 Like

There is trio.current_time. Later on in the docs, it’s even described as being used to implement trio.move_on_after, although according to your post that’s not strictly true.

However, it seems to me like you should just be wrapping the async with trio.open_nursery() block in a with trio.move_on_after(2) block. Since, as you pointed out, start_soon and therefore run_scene are synchronous, run_scene should complete almost instantly, right? That should be good enough to implement your “two seconds after all tasks have spawned” deadline.

1 Like

how my god, how did I miss that…

Since, as you pointed out, start_soon and therefore run_scene are synchronous, run_scene should complete almost instantly, right?

That’s the thing: it doesn’t. It’s a mini game loop (one per scene).

In fact you should be able to implement most regular functions like move_on_after without using _core… the reason Trio has a _core subpackage internally is to collect together the, well, core code that has to have special knowledge of Trio internals and couldn’t be implemented as a third-party library. Everything that _core exports also gets re-exported publicly (in trio, trio.hazmat, or trio.testing, depending on what it is), and everything in trio/*.py is implemented using only these public exports. So anything you see in trio/*.py is stuff that you can reimplement yourself if you wanted to, using only public APIs. The point of _core is to make sure that code like move_on_after isn’t accidentally cheating and using private APIs.

There’s definitely no way you could guess this just from looking at trio/_timeouts.py though… I opened an issue to hopefully help the next person:

1 Like