-
-
Notifications
You must be signed in to change notification settings - Fork 350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wall clock timing functionality #173
Comments
The discussion in #394 got me thinking about this a bit again. Contrary to the discussion in #168, it looks like on MacOS the best way to do this is not On Linux, it isn't 100% clear to me how a I guess the more interesting use case for a clock being stepped is if you have a timer set to "every Saturday at noon" -- in this case if the timer is currently set to the next Saturday – like say it's 2018-01-01, so the timer is set to 2018-01-06 – and then the clock is stepped backwards to 2017-01-01, you don't want to keep sleeping until 2018-01-6, you want to redo the "next Saturday" calculation and reset the timer to a different date (!). Clock change notification is also possible on MacOS by fiddling with Mach ports, as noted here. libdispatch is open source, so you can look at how they do this: Brainstorming possible tr- + time-themed names for a trio wall-clock library: |
Here's the twisted bug in case anyone wants to read 11 years of discussion of this topic: https://twistedmatrix.com/trac/ticket/2424 |
Though most of the discussion in that twisted ticket seems to be about how to untangle themselves from having decided early on to use a mix of monotonic and wall-clock time. (Not really their fault, but they're using wall clock time for calculations, and then calling |
I poked at this a bit more recently. The most interesting discovery is that the Windows "waitable timer" API appears to handle wall clock waits correctly, without needing to do horrible stuff to get This makes this whole project seem much more doable then before: we now have pretty simple/straightforward ways to do this on all three major platforms. It looks like on macOS, the best way to work with GCD is to use pyobjc: https://pyobjc.readthedocs.io/en/latest/notes/framework-wrappers.html So we could basically just have an Biggest open question for me: integration with mock clocks for testing, and libraries like freezegun. I think the most generally-useful semantics for mock datetimes are to make them tightly-integrated with the mock/autojump clock:
So the way this would look to the user is that manually-advancing or autojump-advancing the monotonic clock will automatically move both clocks in sync, and then there's also a way to manually set just the wallclock time without affecting the monotonic clock. In particular, this means that autojumping will automatically work for arbitrary mixes of monotonic deadlines and wallclock-sleeps! Looking at the freezegun source, it has to do some super-gnarly stuff to monkeypatch the stdlib to return the fake datetimes, so we probably don't want to reimplement that part ourselves. But, its policies for controlling the fake clock are a bit baroque and don't fit in nicely with our system. So maybe we need to use freezegun, but substituting in our own fake clock policy? There isn't currently a public API for this, but it looks like it would be easy to add: at the end of the day, all of freezegun's machinery already funnels down to a single function call that returns the current time. The final big question is how to expose the testing machinery: probably we don't want to redefine the existing |
Another wrinkle: we do also support FreeBSD now. I just spent a few minutes checking docs and grepping kernel sources, and AFAICT FreeBSD doesn't have any way to get notified when the clock changes. The best you can do is:
Unfortunately, using signals to wake up threads is very tricky (in particular: as a library, we can't guarantee that any particular signal is available for use; there's also some discussion of this in #174 for interrupting blocking [Edit: could also check whether using |
It's a pity this didn't quite make it to production, especially since it seems like it's mainly because FreeBSD is hard (which is very worthwhile but not the most common case). Perhaps FreeBSD is a rare enough case that it could be dropped, or the problem of picking a signal pushed to the user (you have to make a selection to use the functionality but there's a default and it's only used on BSD)? Is there any other library that implements something like this just for Windows and Linux, even just a blocking API? |
If you just want a hacky solution, you can write a helper function that uses https://docs.python.org/3/library/datetime.html to calculate the time until a certain date/time and then call Looks like there's plenty libraries that has blocking sleeps, e.g. https://pypi.org/project/pause/, https://pypi.org/project/sleep-until/ - though can't vouch for any of them personally. |
This is probably fairly low priority, but: an interesting and sometimes-useful feature is the ability to sleep until a particular wall clock time (e.g., "this cert is expiring at 2017-12-31T12:00:00Z, so I want to wake up 3 days before that so I can renew it"). This is quite different from trio's current timekeeping abilities, which are all oriented around monotonic time (which ignores clock changes, and stops while the computer is suspended, etc.). Really these are just different incommensurable time scales.
Fortunately, I don't think we need the ability to directly set a cancel scope deadline to a particular wall clock time, so this doesn't need to be integrated deep into the guts of trio's run loop. I think it'd be sufficient to provide a
sleep_until_wall_clock_time
(and maybecurrent_wall_clock_time
for completeness).This comment and the replies have some more details on this idea, including notes on how it could be implemented on different systems.
The text was updated successfully, but these errors were encountered: