Simplify Clock/ClockMark design
- Do not require initialElapsed parameter - Introduce instead ClockMark +- Duration operators - Do not require ClockMark to expose its originating Clock back - Turn elapsedFrom property into elapsed() function - Rename abstract clock classes - Fix unit of abstract clocks when constructing them Add top-level docs for Clocks
This commit is contained in:
@@ -5,27 +5,49 @@
|
||||
|
||||
package kotlin.time
|
||||
|
||||
/**
|
||||
* A source of time for measuring time intervals.
|
||||
*
|
||||
* The only operation provided by the clock is [mark]. It returns a [ClockMark], which can be used to query the elapsed time later.
|
||||
*
|
||||
* @see [measureTime]
|
||||
* @see [withMeasureTime]
|
||||
*/
|
||||
public interface Clock {
|
||||
|
||||
/**
|
||||
* Marks a time point on this clock.
|
||||
*
|
||||
* @param initialElapsed An initial value of [ClockMark.elapsedFrom] property of the resulting [ClockMark]:
|
||||
*
|
||||
* - pass [Duration.ZERO] to mark a time point that is now.
|
||||
* - pass a positive duration to mark a time point in the past.
|
||||
* - pass a negative duration to mark a time point in the future.
|
||||
*
|
||||
*/
|
||||
fun mark(initialElapsed: Duration = Duration.ZERO): ClockMark
|
||||
|
||||
companion object {
|
||||
val Default: Clock get() = MonoClock
|
||||
}
|
||||
|
||||
fun mark(): ClockMark
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a time point notched on a particular [Clock]. Remains bound to the clock it was taken from
|
||||
* and allows querying for the duration of time elapsed from that point (see the function [elapsed]).
|
||||
*/
|
||||
public interface ClockMark {
|
||||
val clock: Clock
|
||||
val elapsedFrom: Duration
|
||||
/**
|
||||
* Returns the amount of time passed from this clock mark on the clock from which this mark was taken.
|
||||
*/
|
||||
fun elapsed(): Duration
|
||||
|
||||
/**
|
||||
* Returns a clock mark on the same clock that is ahead of this clock 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.
|
||||
*/
|
||||
operator fun plus(duration: Duration): ClockMark = AdjustedClockMark(this, duration)
|
||||
|
||||
/**
|
||||
* Returns a clock mark on the same clock that is behind this clock 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.
|
||||
*/
|
||||
operator fun minus(duration: Duration): ClockMark = plus(-duration)
|
||||
}
|
||||
|
||||
|
||||
private class AdjustedClockMark(val mark: ClockMark, val adjustment: Duration) : ClockMark {
|
||||
override fun elapsed(): Duration = mark.elapsed() - adjustment
|
||||
|
||||
override fun plus(duration: Duration): ClockMark = AdjustedClockMark(mark, adjustment + duration)
|
||||
}
|
||||
@@ -7,49 +7,54 @@ package kotlin.time
|
||||
|
||||
import kotlin.js.JsName
|
||||
|
||||
/**
|
||||
* The most precise clock available in the platform, whose readings increase monotonically over time.
|
||||
*/
|
||||
public expect object MonoClock : Clock
|
||||
|
||||
/**
|
||||
* An abstract class used to implement clocks that return their readings as [Long] values in the specified [unit].
|
||||
*/
|
||||
public abstract class AbstractLongClock(protected val unit: DurationUnit) : Clock {
|
||||
protected abstract fun read(): Long
|
||||
|
||||
public abstract class LongReadingClock : Clock {
|
||||
abstract fun reading(): Long
|
||||
abstract val unit: DurationUnit
|
||||
|
||||
override fun mark(initialElapsed: Duration): ClockMark = object : ClockMark {
|
||||
val startedAt = reading()
|
||||
override val clock: Clock get() = this@LongReadingClock
|
||||
override val elapsedFrom: Duration get() = Duration(reading() - startedAt, this@LongReadingClock.unit) + initialElapsed
|
||||
override fun mark(): ClockMark = object : ClockMark {
|
||||
val startedAt = read()
|
||||
override fun elapsed(): Duration = Duration(read() - startedAt, this@AbstractLongClock.unit)
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class DoubleReadingClock : Clock {
|
||||
abstract fun reading(): Double
|
||||
abstract val unit: DurationUnit
|
||||
/**
|
||||
* An abstract class used to implement clocks that return their readings as [Double] values in the specified [unit].
|
||||
*/
|
||||
public abstract class AbstractDoubleClock(protected val unit: DurationUnit) : Clock {
|
||||
protected abstract fun read(): Double
|
||||
|
||||
override fun mark(initialElapsed: Duration): ClockMark = object : ClockMark {
|
||||
val startedAt = reading()
|
||||
override val clock: Clock get() = this@DoubleReadingClock
|
||||
override val elapsedFrom: Duration get() = Duration(reading() - startedAt, this@DoubleReadingClock.unit) + initialElapsed
|
||||
override fun mark(): ClockMark = object : ClockMark {
|
||||
val startedAt = read()
|
||||
override fun elapsed(): Duration = Duration(read() - startedAt, this@AbstractDoubleClock.unit)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A clock, whose readings can be preset and changed manually. It is useful as a predictable source of time in tests.
|
||||
*/
|
||||
public class TestClock(
|
||||
@JsName("readingValue")
|
||||
var reading: Long = 0L,
|
||||
override val unit: DurationUnit = DurationUnit.NANOSECONDS
|
||||
) : LongReadingClock() {
|
||||
override fun reading(): Long = reading
|
||||
unit: DurationUnit = DurationUnit.NANOSECONDS
|
||||
) : AbstractLongClock(unit) {
|
||||
override fun read(): Long = reading
|
||||
}
|
||||
|
||||
/*
|
||||
public interface WallClock {
|
||||
fun currentTimeMilliseconds(): Long
|
||||
|
||||
companion object : WallClock, LongReadingClock() {
|
||||
companion object : WallClock, AbstractLongClock(unit = DurationUnit.MILLISECONDS) {
|
||||
override fun currentTimeMilliseconds(): Long = System.currentTimeMillis()
|
||||
override fun reading(): Long = System.currentTimeMillis()
|
||||
override val unit: DurationUnit get() = DurationUnit.MILLISECONDS
|
||||
override fun read(): Long = System.currentTimeMillis()
|
||||
override fun toString(): String = "WallClock(System.currentTimeMillis())"
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -22,7 +22,7 @@ public inline fun Clock.measureTime(action: () -> Unit): Duration {
|
||||
|
||||
val mark = mark()
|
||||
action()
|
||||
return mark.elapsedFrom
|
||||
return mark.elapsed()
|
||||
}
|
||||
|
||||
|
||||
@@ -44,5 +44,5 @@ public inline fun <T> Clock.withMeasureTime(action: () -> T): DurationMeasured<T
|
||||
|
||||
val mark = mark()
|
||||
val result = action()
|
||||
return DurationMeasured(result, mark.elapsedFrom)
|
||||
return DurationMeasured(result, mark.elapsed())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user