Rename Clock to TimeSource, ClockMark to TimeMark

Step 2: rename classes and interfaces.
Provide deprecated typealiases to smooth migration.
This commit is contained in:
Ilya Gorbunov
2020-01-13 21:08:00 +03:00
parent a11a25087a
commit 1336da8453
9 changed files with 194 additions and 155 deletions
+59 -27
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -8,65 +8,80 @@ package kotlin.time
/**
* A source of time for measuring time intervals.
*
* The only operation provided by the clock is [markNow]. It returns a [ClockMark], which can be used to query the elapsed time later.
* The only operation provided by the time source is [markNow]. It returns a [TimeMark], which can be used to query the elapsed time later.
*
* @see [measureTime]
* @see [measureTimedValue]
*/
@SinceKotlin("1.3")
@ExperimentalTime
public interface Clock {
public interface TimeSource {
/**
* Marks a time point on this clock.
* Marks a point in time on this time source.
*
* The returned [ClockMark] instance encapsulates captured time point and allows querying
* the duration of time interval [elapsed][ClockMark.elapsedNow] from that point.
* The returned [TimeMark] instance encapsulates the captured time point and allows querying
* the duration of time interval [elapsed][TimeMark.elapsedNow] from that point.
*/
public fun markNow(): ClockMark
public fun markNow(): TimeMark
/**
* The most precise time source available in the platform.
*
* This time source returns its readings from a source of monotonic time when it is available in a target platform,
* and resorts to a non-monotonic time source otherwise.
*/
public object Monotonic : TimeSource by MonotonicTimeSource {
override fun toString(): String = MonotonicTimeSource.toString()
}
public companion object {
}
}
/**
* Represents a time point notched on a particular [Clock]. Remains bound to the clock it was taken from
* Represents a time point notched on a particular [TimeSource]. Remains bound to the time source it was taken from
* and allows querying for the duration of time elapsed from that point (see the function [elapsedNow]).
*/
@SinceKotlin("1.3")
@ExperimentalTime
public abstract class ClockMark {
public abstract class TimeMark {
/**
* Returns the amount of time passed from this clock mark on the clock from which this mark was taken.
* Returns the amount of time passed from this mark measured with the time source from which this mark was taken.
*
* Note that the value returned by this function can change on subsequent invocations.
*/
public abstract fun elapsedNow(): Duration
/**
* Returns a clock mark on the same clock that is ahead of this clock mark by the specified [duration].
* Returns a time mark on the same time source that is ahead of this time mark by the specified [duration].
*
* The returned clock mark is more _late_ when the [duration] is positive, and more _early_ when the [duration] is negative.
* The returned time mark is more _late_ when the [duration] is positive, and more _early_ when the [duration] is negative.
*/
public open operator fun plus(duration: Duration): ClockMark = AdjustedClockMark(this, duration)
public open operator fun plus(duration: Duration): TimeMark = AdjustedTimeMark(this, duration)
/**
* Returns a clock mark on the same clock that is behind this clock mark by the specified [duration].
* Returns a time mark on the same time source that is behind this time mark by the specified [duration].
*
* The returned clock mark is more _early_ when the [duration] is positive, and more _late_ when the [duration] is negative.
* The returned time mark is more _early_ when the [duration] is positive, and more _late_ when the [duration] is negative.
*/
public open operator fun minus(duration: Duration): ClockMark = plus(-duration)
public open operator fun minus(duration: Duration): TimeMark = plus(-duration)
/**
* Returns true if this clock mark has passed according to the clock from which this mark was taken.
* Returns true if this time mark has passed according to the time source from which this mark was taken.
*
* Note that the value returned by this function can change on subsequent invocations.
* If the clock is monotonic, it can change only from `false` to `true`, namely, when the clock mark becomes behind the current point of the clock.
* If the time source is monotonic, it can change only from `false` to `true`, namely, when the time mark becomes behind the current point of the time source.
*/
public fun hasPassedNow(): Boolean = !elapsedNow().isNegative()
/**
* Returns false if this clock mark has not passed according to the clock from which this mark was taken.
* Returns false if this time mark has not passed according to the time source from which this mark was taken.
*
* Note that the value returned by this function can change on subsequent invocations.
* If the clock is monotonic, it can change only from `true` to `false`, namely, when the clock mark becomes behind the current point of the clock.
* If the time source is monotonic, it can change only from `true` to `false`, namely, when the time mark becomes behind the current point of the time source.
*/
public fun hasNotPassedNow(): Boolean = elapsedNow().isNegative()
}
@@ -75,19 +90,36 @@ public abstract class ClockMark {
@ExperimentalTime
@SinceKotlin("1.3")
@kotlin.internal.InlineOnly
@Deprecated("Subtracting one ClockMark from another is not a well defined operation because these clock marks could have been obtained from the different clocks.", level = DeprecationLevel.ERROR)
public inline operator fun ClockMark.minus(other: ClockMark): Duration = throw Error("Operation is disallowed.")
@Deprecated(
"Subtracting one TimeMark from another is not a well defined operation because these time marks could have been obtained from the different time sources.",
level = DeprecationLevel.ERROR
)
public inline operator fun TimeMark.minus(other: TimeMark): Duration = throw Error("Operation is disallowed.")
@ExperimentalTime
@SinceKotlin("1.3")
@kotlin.internal.InlineOnly
@Deprecated("Comparing one ClockMark to another is not a well defined operation because these clock marks could have been obtained from the different clocks.", level = DeprecationLevel.ERROR)
public inline operator fun ClockMark.compareTo(other: ClockMark): Int = throw Error("Operation is disallowed.")
@Deprecated(
"Comparing one TimeMark to another is not a well defined operation because these time marks could have been obtained from the different time sources.",
level = DeprecationLevel.ERROR
)
public inline operator fun TimeMark.compareTo(other: TimeMark): Int = throw Error("Operation is disallowed.")
@ExperimentalTime
private class AdjustedClockMark(val mark: ClockMark, val adjustment: Duration) : ClockMark() {
private class AdjustedTimeMark(val mark: TimeMark, val adjustment: Duration) : TimeMark() {
override fun elapsedNow(): Duration = mark.elapsedNow() - adjustment
override fun plus(duration: Duration): ClockMark = AdjustedClockMark(mark, adjustment + duration)
}
override fun plus(duration: Duration): TimeMark = AdjustedTimeMark(mark, adjustment + duration)
}
@SinceKotlin("1.3")
@ExperimentalTime
@Deprecated("Use TimeSource interface instead.", ReplaceWith("TimeSource", "kotlin.time.TimeSource"))
public typealias Clock = TimeSource
@SinceKotlin("1.3")
@ExperimentalTime
@Deprecated("Use TimeMark class instead.", ReplaceWith("TimeMark", "kotlin.time.TimeMark"))
public typealias ClockMark = TimeMark
+46 -44
View File
@@ -1,91 +1,85 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package kotlin.time
/**
* The most precise clock available in the platform.
*
* The clock returns its readings from a source of monotonic time when it is available in a target platform,
* and resorts to a non-monotonic time source otherwise.
*/
@SinceKotlin("1.3")
@ExperimentalTime
public expect object MonoClock : Clock
internal expect object MonotonicTimeSource : TimeSource
/**
* An abstract class used to implement clocks that return their readings as [Long] values in the specified [unit].
* An abstract class used to implement time sources that return their readings as [Long] values in the specified [unit].
*
* @property unit The unit in which this clock readings are expressed.
* @property unit The unit in which this time source's readings are expressed.
*/
@SinceKotlin("1.3")
@ExperimentalTime
public abstract class AbstractLongClock(protected val unit: DurationUnit) : Clock {
public abstract class AbstractLongTimeSource(protected val unit: DurationUnit) : TimeSource {
/**
* This protected method should be overridden to return the current reading of the clock expressed as a [Long] number
* This protected method should be overridden to return the current reading of the time source expressed as a [Long] number
* in the unit specified by the [unit] property.
*/
protected abstract fun read(): Long
private class LongClockMark(private val startedAt: Long, private val clock: AbstractLongClock, private val offset: Duration) : ClockMark() {
override fun elapsedNow(): Duration = (clock.read() - startedAt).toDuration(clock.unit) - offset
override fun plus(duration: Duration): ClockMark = LongClockMark(startedAt, clock, offset + duration)
private class LongTimeMark(private val startedAt: Long, private val timeSource: AbstractLongTimeSource, private val offset: Duration) : TimeMark() {
override fun elapsedNow(): Duration = (timeSource.read() - startedAt).toDuration(timeSource.unit) - offset
override fun plus(duration: Duration): TimeMark = LongTimeMark(startedAt, timeSource, offset + duration)
}
override fun markNow(): ClockMark = LongClockMark(read(), this, Duration.ZERO)
override fun markNow(): TimeMark = LongTimeMark(read(), this, Duration.ZERO)
}
/**
* An abstract class used to implement clocks that return their readings as [Double] values in the specified [unit].
* An abstract class used to implement time sources that return their readings as [Double] values in the specified [unit].
*
* @property unit The unit in which this clock readings are expressed.
* @property unit The unit in which this time source's readings are expressed.
*/
@SinceKotlin("1.3")
@ExperimentalTime
public abstract class AbstractDoubleClock(protected val unit: DurationUnit) : Clock {
public abstract class AbstractDoubleTimeSource(protected val unit: DurationUnit) : TimeSource {
/**
* This protected method should be overridden to return the current reading of the clock expressed as a [Double] number
* This protected method should be overridden to return the current reading of the time source expressed as a [Double] number
* in the unit specified by the [unit] property.
*/
protected abstract fun read(): Double
private class DoubleClockMark(private val startedAt: Double, private val clock: AbstractDoubleClock, private val offset: Duration) : ClockMark() {
override fun elapsedNow(): Duration = (clock.read() - startedAt).toDuration(clock.unit) - offset
override fun plus(duration: Duration): ClockMark = DoubleClockMark(startedAt, clock, offset + duration)
private class DoubleTimeMark(private val startedAt: Double, private val timeSource: AbstractDoubleTimeSource, private val offset: Duration) : TimeMark() {
override fun elapsedNow(): Duration = (timeSource.read() - startedAt).toDuration(timeSource.unit) - offset
override fun plus(duration: Duration): TimeMark = DoubleTimeMark(startedAt, timeSource, offset + duration)
}
override fun markNow(): ClockMark = DoubleClockMark(read(), this, Duration.ZERO)
override fun markNow(): TimeMark = DoubleTimeMark(read(), this, Duration.ZERO)
}
/**
* A clock that has programmatically updatable readings. It is useful as a predictable source of time in tests.
* A time source that has programmatically updatable readings. It is useful as a predictable source of time in tests.
*
* The current clock reading value can be advanced by the specified duration amount with the operator [plusAssign]:
* The current reading value can be advanced by the specified duration amount with the operator [plusAssign]:
*
* ```
* val clock = TestClock()
* clock += 10.seconds
* val timeSource = TestTimeSource()
* timeSource += 10.seconds
* ```
*
* Implementation note: the current clock reading value is stored as a [Long] number of nanoseconds,
* Implementation note: the current reading value is stored as a [Long] number of nanoseconds,
* thus it's capable to represent a time range of approximately ±292 years.
* Should the reading value overflow as the result of [plusAssign] operation, an [IllegalStateException] is thrown.
*/
@SinceKotlin("1.3")
@ExperimentalTime
public class TestClock : AbstractLongClock(unit = DurationUnit.NANOSECONDS) {
public class TestTimeSource : AbstractLongTimeSource(unit = DurationUnit.NANOSECONDS) {
private var reading: Long = 0L
override fun read(): Long = reading
/**
* Advances the current reading value of this clock by the specified [duration].
* Advances the current reading value of this time source by the specified [duration].
*
* [duration] value is rounded down towards zero when converting it to a [Long] number of nanoseconds.
* For example, if the duration being added is `0.6.nanoseconds`, the clock reading won't advance because
* the duration value will be rounded to zero nanoseconds.
* For example, if the duration being added is `0.6.nanoseconds`, the reading doesn't advance because
* the duration value is rounded to zero nanoseconds.
*
* @throws IllegalStateException when the reading value overflows as the result of this operation.
*/
@@ -106,18 +100,26 @@ public class TestClock : AbstractLongClock(unit = DurationUnit.NANOSECONDS) {
}
private fun overflow(duration: Duration) {
throw IllegalStateException("TestClock will overflow if its reading ${reading}ns is advanced by $duration.")
throw IllegalStateException("TestTimeSource will overflow if its reading ${reading}ns is advanced by $duration.")
}
}
/*
public interface WallClock {
fun currentTimeMilliseconds(): Long
@SinceKotlin("1.3")
@ExperimentalTime
@Deprecated("Use TimeSource.Monotonic instead.", ReplaceWith("TimeSource.Monotonic", "kotlin.time.TimeSource"))
public typealias MonoClock = TimeSource.Monotonic
companion object : WallClock, AbstractLongClock(unit = DurationUnit.MILLISECONDS) {
override fun currentTimeMilliseconds(): Long = System.currentTimeMillis()
override fun read(): Long = System.currentTimeMillis()
override fun toString(): String = "WallClock(System.currentTimeMillis())"
}
}
*/
@SinceKotlin("1.3")
@ExperimentalTime
@Deprecated("Use AbstractLongTimeSource instead.", ReplaceWith("AbstractLongTimeSource", "kotlin.time.AbstractLongTimeSource"))
public typealias AbstractLongClock = AbstractLongTimeSource
@SinceKotlin("1.3")
@ExperimentalTime
@Deprecated("Use AbstractDoubleTimeSource instead.", ReplaceWith("AbstractDoubleTimeSource", "kotlin.time.AbstractDoubleTimeSource"))
public typealias AbstractDoubleClock = AbstractDoubleTimeSource
@SinceKotlin("1.3")
@ExperimentalTime
@Deprecated("Use TestTimeSource instead.", ReplaceWith("TestTimeSource", "kotlin.time.TestTimeSource"))
public typealias TestClock = TestTimeSource
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -10,7 +10,7 @@ import kotlin.contracts.*
/**
* Executes the given function [block] and returns the duration of elapsed time interval.
*
* The elapsed time is measured with [MonoClock].
* The elapsed time is measured with [TimeSource.Monotonic].
*/
@SinceKotlin("1.3")
@ExperimentalTime
@@ -18,18 +18,18 @@ public inline fun measureTime(block: () -> Unit): Duration {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return MonoClock.measureTime(block)
return TimeSource.Monotonic.measureTime(block)
}
/**
* Executes the given function [block] and returns the duration of elapsed time interval.
*
* The elapsed time is measured with the specified `this` [Clock] instance.
* The elapsed time is measured with the specified `this` [TimeSource] instance.
*/
@SinceKotlin("1.3")
@ExperimentalTime
public inline fun Clock.measureTime(block: () -> Unit): Duration {
public inline fun TimeSource.measureTime(block: () -> Unit): Duration {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
@@ -54,7 +54,7 @@ public data class TimedValue<T>(val value: T, val duration: Duration)
* Executes the given function [block] and returns an instance of [TimedValue] class, containing both
* the result of the function execution and the duration of elapsed time interval.
*
* The elapsed time is measured with [MonoClock].
* The elapsed time is measured with [TimeSource.Monotonic].
*/
@SinceKotlin("1.3")
@ExperimentalTime
@@ -63,18 +63,18 @@ public inline fun <T> measureTimedValue(block: () -> T): TimedValue<T> {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return MonoClock.measureTimedValue(block)
return TimeSource.Monotonic.measureTimedValue(block)
}
/**
* Executes the given [block] and returns an instance of [TimedValue] class, containing both
* the result of function execution and the duration of elapsed time interval.
*
* The elapsed time is measured with the specified `this` [Clock] instance.
* The elapsed time is measured with the specified `this` [TimeSource] instance.
*/
@SinceKotlin("1.3")
@ExperimentalTime
public inline fun <T> Clock.measureTimedValue(block: () -> T): TimedValue<T> {
public inline fun <T> TimeSource.measureTimedValue(block: () -> T): TimedValue<T> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}