In the discussion of RFC0014 it became apparent that the Time::Span type can lead to confusion. Its primary purpose is to represent a duration of time. But we also use it for a reading of the monotonic clock (Time.monotonic). This makes some sense because the monotonic clock is just the time elapsed since some arbitrary point in time.
But this double use leads to problems when specifying some kind of timeout or delay: A duration represents a relative distance from the current instant. A monotonic clock reading represents an absolute instant. Either semantic is valid. And the type system makes it impossible to tell them apart.
The first proposal for a monotonic clock was actually for Clock.monotonic (#3826), but somehow - after intricate discussions about involving Time and whether monotonic readings are even necessary on their own - we ended up piggy-bagging Time.monotonic on Time::Span (#5108). I believe it was mostly for the sake of simplicity?
Maybe itās time to rethink that? Having a separate type to represent a monotonic clock reading would be very helpful for use cases such as Fiber.timeout: A Time::Span argument represents a relative duration, a Time::Monotonic (working title) argument represents an absolute instant.
The only affected stdlib API would be Time.monotonic. It would be relatively easy to deprecate that and replace it with, for example Time::Monotonic.now, or Time::Clock.now.
Clocks might be interesting to have. We could have clock-aware sleeps and timeouts, like wait until 5 pm (real time) or wait until 10 monotonic seconds have passed.
Iād actually just consider a type for a clock reading, i.e. a representation for an instant in the monotonic clockās timeline.
Thereās no need for a dedicated type for a monotonic clock. We just need a single class method to get the current instant. Thatās it.
Throwing together monotonic time and non-monotonic wall time does not sound like a good idea. At least none that I would like to pursue. Impossible to get right. Theyāre different clocks for a reason.
Oh sorry, I wasnāt suggesting we add a dedicated type for diff kinds of clocks. But instead having it not return Time::Span could make it so itās easier to resolve Time.montonic to a wallclock time if so desired (instead of the silly nanosecond math stuff I have to do currenlty); maybe via some #to_* method on the new return type.
Iāve never inspected the value of the return value of Time.monotonic until right this moment. I knew it was a Time::Span but always assumed it was the duration since the process started. I honestly had no idea what the values were.
I think Time::Instant is a better name and could be used instead of Time::Monotonic, you know itās a good name when you use it to describe what it means.
I like the argument. But I fear this name would be too imprecise and create a new ambiguity: Time also represents an instant, just on a different timeline.
Time::MonotonicInstant would be sufficiently specific, but I figure it could just be shortened to Time::Monotonic.
Perhaps Time::Tick could also be an option. But I find the name Monotonic most suitable because it resembles the existing Time.monotonic method.
Having the result of 10.seconds and Time.monotonic be separate types is a very good idea; itās something that has caused me accidental confusion at times. (Not because I misunderstood, but because I was sleepy and it compiled, so I assumed I hadnāt made any major mistakes⦠it took me a while to find it!)
One could make a struct Time::Monotonic that was just a light wrapper around a Time::Span solely to keep the compiler from letting the user mix them without explicitly casting it⦠that could greatly reduce the tendency of the barrel of the gun to point at our feet, while not being very complex. Then the docs would just need to explain succinctly the reason for it to be a separate thing, which at least at a surface level wouldnāt need to be very wordy.
every time I think of timers for loops I always go back to this blog post. Timeouts and cancellation for humans ā njs blog . I think we should abstract timeout and other reasons to cancel into a cancellation token - there are other reasons to abort async code besides timeouts
Thatās a great resource. Iām familiar with Goās context module, which implements the same thing.
This might be more relevant input for RFC 0014, though?