Hi Levente,
On Wed, Mar 23, 2016 at 05:01:35PM +0100, Levente Uzonyi wrote:
On Sun, 20 Mar 2016, David T. Lewis wrote:
The four policies are:
#acceptPlatformTime - Accept the time value provided by the system platform, even in this allows time to appear to move backwards when the clock is adjusted. Simple, fast, and no hidden side effects.
#monotonicAllowDuplicates - Accept the time value provided by the system platform unless it is less that the last clock tick. This protects for system clock adjustments. Side effects unlikely. Does not ensure unique values on repeated calls.
#monotonicForceMicrosecondIncrement - If the time value is less than or equal to the value from the last call, force increment by one microsecond. This ensures integral values of UTC time, but increments the time value by a full microsecond.
#monotonicForceNanosecondIncrement - If the time value is less than or equal to the value from the last call, force increment by one nanosecond. This it functionally compatible with previous Squeak practice, but is computationally expensive and results in time values represented as fractions, which might be a problem for some database applications.
I think this covers most possible use cases. What I was originally thinking about was the addition of another field to hold the nanosecond part, since that would have only been set by the image itself, so the primitive could still have been used to initialize the rest. That we we could have avoided the use of fractions at the cost of having another field per object even when there's no need for high accuracy.
I'm actually quite happy with the idea of the value being a Number that is an Integer for all reasonable values that could ever be supplied by the VM, but that might be a Fraction if we want to represent time values at some higher precision. Mainly I like it because it seems good conceptually to think of time as continuous, and not as discreet ticks of a clock.
It also works well computationally, because the normal case uses integer values (immediates in 64-bit Spur), and because Fractions involve two integer values, which presumably would be no worse than a design that added another field. But given that none of our computers or VMs can report time to a precision greater than microseconds, I think that we can safely ignore the issue for another 20 years or so ;-)
One more thing that I noticed is that this primitive still uses the "quick but inaccurate" way to get the current time, which only updates every two milliseconds (I think once per heartbeat). Eliot has changed primitive 240 a while ago to always provide the accurate time:
| start end | start := DateAndTime now. [ (end := DateAndTime now) = start ] whileTrue. { start. end. end - start } {2016-03-23T16:53:33.637835+01:00 . 2016-03-23T16:53:33.639844+01:00 . 0:00:00:00.002009}
| start end | start := Time utcMicrosecondClock. [ (end := Time utcMicrosecondClock) = start ] whileTrue. { start. end. end - start } #(3636201206461149 3636201206461150 1)
There is a good implementation of the primitive in the trunk SVN branch that needs to be added to the oscog branch. I think that will take care of the problem. I promised Eliot I would move the code over, but it might be a couple of weeks before I can get to it. We need to add this to the platform code to provide a true atomic primitive (from sq.h):
sqInt ioUtcWithOffset(sqLong*, int*); /* primitiveUtcWithOffset */
And then the primitive (slang) can be updated to match. I am afraid that I am responsible for some of the confusion, because when this was added to Cog a number of years ago, I did not want to touch the platform code, and I implemented a rather kludgy workaround just to get it working. Sorry.
Dave