Initial prototype of Duration and Clocks API
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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
|
||||
|
||||
public actual enum class DurationUnit {
|
||||
/**
|
||||
* Time unit representing one nanosecond, which is 1/1000 of a microsecond.
|
||||
*/
|
||||
NANOSECONDS,
|
||||
/**
|
||||
* Time unit representing one microsecond, which is 1/1000 of a millisecond.
|
||||
*/
|
||||
MICROSECONDS,
|
||||
/**
|
||||
* Time unit representing one millisecond, which is 1/1000 of a second.
|
||||
*/
|
||||
MILLISECONDS,
|
||||
/**
|
||||
* Time unit representing one second.
|
||||
*/
|
||||
SECONDS,
|
||||
/**
|
||||
* Time unit representing one minute.
|
||||
*/
|
||||
MINUTES,
|
||||
/**
|
||||
* Time unit representing one hour.
|
||||
*/
|
||||
HOURS,
|
||||
/**
|
||||
* Time unit representing one day, which always equals 24 hours.
|
||||
*/
|
||||
DAYS;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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
|
||||
|
||||
public actual object MonoClock : Clock {
|
||||
override fun mark(initialElapsed: Duration): ClockMark {
|
||||
TODO("not implemented: base on high-res browser or node perf counter")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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
|
||||
|
||||
public actual fun convertDurationUnit(value: Double, sourceUnit: DurationUnit, targetUnit: DurationUnit): Double {
|
||||
TODO("not implemented")
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
internal actual fun formatToDecimals(value: Double, decimals: Int, unitName: String): String {
|
||||
TODO("not implemented")
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass()
|
||||
@file:kotlin.jvm.JvmName("DurationUnitKt")
|
||||
|
||||
package kotlin.time
|
||||
|
||||
//Actual typealias 'DurationUnit' has no corresponding expected declaration
|
||||
//The following declaration is incompatible because modality is different:
|
||||
// public final expect enum class DurationUnit : Enum<DurationUnit>
|
||||
|
||||
@Suppress("ACTUAL_WITHOUT_EXPECT")
|
||||
public actual typealias DurationUnit = java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
public actual fun convertDurationUnit(value: Double, sourceUnit: DurationUnit, targetUnit: DurationUnit): Double {
|
||||
val sourceInTargets = targetUnit.convert(1, sourceUnit)
|
||||
if (sourceInTargets > 0)
|
||||
return value * sourceInTargets
|
||||
|
||||
val otherInThis = sourceUnit.convert(1, targetUnit)
|
||||
return value / otherInThis
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
public actual object MonoClock : LongReadingClock(), Clock { // TODO: interface should not be required here
|
||||
override fun reading(): Long = System.nanoTime()
|
||||
override fun toString(): String = "Clock(System.nanoTime())"
|
||||
override val unit: DurationUnit = DurationUnit.NANOSECONDS
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
import java.util.*
|
||||
|
||||
internal actual fun formatToDecimals(value: Double, decimals: Int, unitName: String): String =
|
||||
String.format(Locale.ROOT, "%.${decimals}f%s", value, unitName)
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface ClockMark {
|
||||
val clock: Clock
|
||||
val elapsedFrom: Duration
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
import kotlin.js.JsName
|
||||
|
||||
public expect object MonoClock : Clock
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class DoubleReadingClock : Clock {
|
||||
abstract fun reading(): Double
|
||||
abstract val unit: DurationUnit
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class TestClock(
|
||||
@JsName("readingValue")
|
||||
var reading: Long = 0L,
|
||||
override val unit: DurationUnit = DurationUnit.NANOSECONDS
|
||||
) : LongReadingClock() {
|
||||
override fun reading(): Long = reading
|
||||
}
|
||||
|
||||
/*
|
||||
public interface WallClock {
|
||||
fun currentTimeMilliseconds(): Long
|
||||
|
||||
companion object : WallClock, LongReadingClock() {
|
||||
override fun currentTimeMilliseconds(): Long = System.currentTimeMillis()
|
||||
override fun reading(): Long = System.currentTimeMillis()
|
||||
override val unit: DurationUnit get() = DurationUnit.MILLISECONDS
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
private val storageUnit = DurationUnit.MICROSECONDS
|
||||
|
||||
@Suppress("NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
|
||||
public inline class Duration internal constructor(internal val _value: Double) : Comparable<Duration> {
|
||||
// TODO: backend fails on init block, wait for KT-28055
|
||||
|
||||
// init {
|
||||
// require(_value.isNaN().not())
|
||||
// }
|
||||
|
||||
companion object {
|
||||
val ZERO: Duration = Duration(0.0)
|
||||
val MAX_VALUE: Duration = Duration(Double.MAX_VALUE)
|
||||
val MIN_VALUE: Duration = Duration(-Double.MAX_VALUE)
|
||||
val INFINITE: Duration = Duration(Double.POSITIVE_INFINITY)
|
||||
|
||||
|
||||
// constructing from number of units
|
||||
// option 1: static-like constructor functions
|
||||
|
||||
fun days(value: Int) = Duration(value, DurationUnit.DAYS)
|
||||
fun days(value: Long) = Duration(value, DurationUnit.DAYS)
|
||||
fun days(value: Double) = Duration(value, DurationUnit.DAYS)
|
||||
fun hours(value: Int) = Duration(value, DurationUnit.HOURS)
|
||||
fun hours(value: Long) = Duration(value, DurationUnit.HOURS)
|
||||
fun hours(value: Double) = Duration(value, DurationUnit.HOURS)
|
||||
fun minutes(value: Int) = Duration(value, DurationUnit.MINUTES)
|
||||
fun minutes(value: Long) = Duration(value, DurationUnit.MINUTES)
|
||||
fun minutes(value: Double) = Duration(value, DurationUnit.MINUTES)
|
||||
fun seconds(value: Int) = Duration(value, DurationUnit.SECONDS)
|
||||
fun seconds(value: Long) = Duration(value, DurationUnit.SECONDS)
|
||||
fun seconds(value: Double) = Duration(value, DurationUnit.SECONDS)
|
||||
fun milliseconds(value: Int) = Duration(value, DurationUnit.MILLISECONDS)
|
||||
fun milliseconds(value: Long) = Duration(value, DurationUnit.MILLISECONDS)
|
||||
fun milliseconds(value: Double) = Duration(value, DurationUnit.MILLISECONDS)
|
||||
fun microseconds(value: Int) = Duration(value, DurationUnit.MICROSECONDS)
|
||||
fun microseconds(value: Long) = Duration(value, DurationUnit.MICROSECONDS)
|
||||
fun microseconds(value: Double) = Duration(value, DurationUnit.MICROSECONDS)
|
||||
fun nanoseconds(value: Int) = Duration(value, DurationUnit.NANOSECONDS)
|
||||
fun nanoseconds(value: Long) = Duration(value, DurationUnit.NANOSECONDS)
|
||||
fun nanoseconds(value: Double) = Duration(value, DurationUnit.NANOSECONDS)
|
||||
}
|
||||
|
||||
|
||||
// constructing from number of units
|
||||
// option 0: constructors
|
||||
|
||||
// unit is lost after construction
|
||||
|
||||
constructor(value: Int, unit: DurationUnit) : this(convertDurationUnit(value.toDouble(), unit, storageUnit))
|
||||
constructor(value: Long, unit: DurationUnit) : this(convertDurationUnit(value.toDouble(), unit, storageUnit))
|
||||
constructor(value: Double, unit: DurationUnit) : this(convertDurationUnit(value, unit, storageUnit))
|
||||
|
||||
|
||||
// arithmetic operators
|
||||
|
||||
operator fun unaryMinus(): Duration = Duration(-_value)
|
||||
operator fun plus(other: Duration): Duration = Duration(_value + other._value)
|
||||
operator fun minus(other: Duration): Duration = Duration(_value - other._value)
|
||||
|
||||
// should we declare symmetric extension operators?
|
||||
|
||||
operator fun times(scale: Int): Duration = Duration(_value * scale)
|
||||
operator fun times(scale: Double): Duration = Duration(_value * scale)
|
||||
|
||||
operator fun div(scale: Int): Duration = Duration(_value / scale)
|
||||
operator fun div(scale: Double): Duration = Duration(_value / scale)
|
||||
|
||||
operator fun div(other: Duration): Double = this._value / other._value
|
||||
|
||||
fun isNegative(): Boolean = _value < 0
|
||||
fun isInfinite(): Boolean = _value.isInfinite()
|
||||
fun isFinite(): Boolean = _value.isFinite()
|
||||
|
||||
fun absoluteValue(): Duration = if (isNegative()) -this else this
|
||||
|
||||
|
||||
override fun compareTo(other: Duration): Int = this._value.compareTo(other._value)
|
||||
|
||||
|
||||
// splitting to components
|
||||
|
||||
// problem: withComponents can be confused with 'wither' function
|
||||
// perhaps better name would be 'letComponents'
|
||||
|
||||
inline fun <T> withComponents(action: (hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T =
|
||||
action(inHours.toInt(), minutesComponent.toInt(), secondsComponent.toInt(), (inNanoseconds % 1e9).toInt())
|
||||
|
||||
inline fun <T> withComponents(action: (days: Int, hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T =
|
||||
action(inDays.toInt(), hoursComponent.toInt(), minutesComponent.toInt(), secondsComponent.toInt(), (inNanoseconds % 1e9).toInt())
|
||||
|
||||
|
||||
@PublishedApi
|
||||
internal val hoursComponent: Double get() = inHours % 24
|
||||
@PublishedApi
|
||||
internal val minutesComponent: Double get() = inMinutes % 60
|
||||
@PublishedApi
|
||||
internal val secondsComponent: Double get() = inSeconds % 60
|
||||
|
||||
|
||||
// conversion to units
|
||||
|
||||
// option 1: in- properties
|
||||
|
||||
val inDays: Double get() = inUnits(DurationUnit.DAYS)
|
||||
val inHours: Double get() = inUnits(DurationUnit.HOURS)
|
||||
val inMinutes: Double get() = inUnits(DurationUnit.MINUTES)
|
||||
val inSeconds: Double get() = inUnits(DurationUnit.SECONDS)
|
||||
val inMilliseconds: Double get() = inUnits(DurationUnit.MILLISECONDS)
|
||||
val inMicroseconds: Double get() = inUnits(DurationUnit.MICROSECONDS)
|
||||
val inNanoseconds: Double get() = inUnits(DurationUnit.NANOSECONDS)
|
||||
|
||||
fun inUnits(unit: DurationUnit) = convertDurationUnit(_value, storageUnit, unit)
|
||||
|
||||
// option 2: to- functions
|
||||
|
||||
fun toDays(): Double = toUnits(DurationUnit.DAYS)
|
||||
fun toHours(): Double = toUnits(DurationUnit.HOURS)
|
||||
fun toMinutes(): Double = toUnits(DurationUnit.MINUTES)
|
||||
fun toSeconds(): Double = toUnits(DurationUnit.SECONDS)
|
||||
fun toMilliseconds(): Double = toUnits(DurationUnit.MILLISECONDS)
|
||||
fun toMicroseconds(): Double = toUnits(DurationUnit.MICROSECONDS)
|
||||
fun toNanoseconds(): Double = toUnits(DurationUnit.NANOSECONDS)
|
||||
|
||||
fun toUnits(unit: DurationUnit): Double = convertDurationUnit(_value, storageUnit, unit)
|
||||
|
||||
|
||||
override fun toString(): String = buildString {
|
||||
if (isInfinite()) {
|
||||
if (isNegative()) append('-')
|
||||
append("INFINITY")
|
||||
} else {
|
||||
// TODO: Find the most appropriate representation
|
||||
append(_value)
|
||||
append(storageUnit.shortName())
|
||||
}
|
||||
}
|
||||
|
||||
fun toString(unit: DurationUnit, decimals: Int = 0): String {
|
||||
// if (decimals == 0) return toString(unit)
|
||||
return formatToDecimals(inUnits(unit), decimals, unit.shortName())
|
||||
}
|
||||
|
||||
|
||||
fun toIsoString(): String = buildString {
|
||||
if (isNegative()) append('-')
|
||||
append('P')
|
||||
absoluteValue().withComponents { days, hours, minutes, seconds, nanoseconds ->
|
||||
if (days != 0)
|
||||
append(days).append('D')
|
||||
|
||||
|
||||
if (days == 0 || seconds != 0 || nanoseconds != 0 || minutes != 0 || hours != 0) {
|
||||
append('T')
|
||||
val hasHours = hours != 0 || days != 0
|
||||
val hasSeconds = seconds != 0 || nanoseconds != 0
|
||||
val hasMinutes = minutes != 0 || (hasSeconds && hasHours)
|
||||
if (hasHours) {
|
||||
append(hours).append('H')
|
||||
}
|
||||
if (hasMinutes) {
|
||||
append(minutes).append('M')
|
||||
}
|
||||
if (hasSeconds || (!hasHours && !hasMinutes)) {
|
||||
append(seconds)
|
||||
if (nanoseconds != 0) {
|
||||
append('.')
|
||||
val nss = nanoseconds.toString().padStart(9, '0')
|
||||
when {
|
||||
nanoseconds % 1_000_000 == 0 -> append(nss, 0, 3)
|
||||
nanoseconds % 1_000 == 0 -> append(nss, 0, 6)
|
||||
else -> append(nss)
|
||||
}
|
||||
}
|
||||
append('S')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// constructing from number of units
|
||||
// option 2: constructor extension functions
|
||||
|
||||
|
||||
val Int.nanoseconds get() = Duration(this, DurationUnit.NANOSECONDS)
|
||||
val Long.nanoseconds get() = Duration(this, DurationUnit.NANOSECONDS)
|
||||
val Double.nanoseconds get() = Duration(this, DurationUnit.NANOSECONDS)
|
||||
|
||||
val Int.microseconds get() = Duration(this, DurationUnit.MICROSECONDS)
|
||||
val Long.microseconds get() = Duration(this, DurationUnit.MICROSECONDS)
|
||||
val Double.microseconds get() = Duration(this, DurationUnit.MICROSECONDS)
|
||||
|
||||
val Int.milliseconds get() = Duration(this, DurationUnit.MILLISECONDS)
|
||||
val Long.milliseconds get() = Duration(this, DurationUnit.MILLISECONDS)
|
||||
val Double.milliseconds get() = Duration(this, DurationUnit.MILLISECONDS)
|
||||
|
||||
val Int.seconds get() = Duration(this, DurationUnit.SECONDS)
|
||||
val Long.seconds get() = Duration(this, DurationUnit.SECONDS)
|
||||
val Double.seconds get() = Duration(this, DurationUnit.SECONDS)
|
||||
|
||||
val Int.minutes get() = Duration(this, DurationUnit.MINUTES)
|
||||
val Long.minutes get() = Duration(this, DurationUnit.MINUTES)
|
||||
val Double.minutes get() = Duration(this, DurationUnit.MINUTES)
|
||||
|
||||
val Int.hours get() = Duration(this, DurationUnit.HOURS)
|
||||
val Long.hours get() = Duration(this, DurationUnit.HOURS)
|
||||
val Double.hours get() = Duration(this, DurationUnit.HOURS)
|
||||
|
||||
val Int.days get() = Duration(this, DurationUnit.DAYS)
|
||||
val Long.days get() = Duration(this, DurationUnit.DAYS)
|
||||
val Double.days get() = Duration(this, DurationUnit.DAYS)
|
||||
|
||||
|
||||
|
||||
internal expect fun formatToDecimals(value: Double, decimals: Int, unitName: String): String
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass()
|
||||
@file:kotlin.jvm.JvmName("DurationUnitKt")
|
||||
|
||||
package kotlin.time
|
||||
|
||||
|
||||
public expect enum class DurationUnit {
|
||||
/**
|
||||
* Time unit representing one nanosecond, which is 1/1000 of a microsecond.
|
||||
*/
|
||||
NANOSECONDS,
|
||||
/**
|
||||
* Time unit representing one microsecond, which is 1/1000 of a millisecond.
|
||||
*/
|
||||
MICROSECONDS,
|
||||
/**
|
||||
* Time unit representing one millisecond, which is 1/1000 of a second.
|
||||
*/
|
||||
MILLISECONDS,
|
||||
/**
|
||||
* Time unit representing one second.
|
||||
*/
|
||||
SECONDS,
|
||||
/**
|
||||
* Time unit representing one minute.
|
||||
*/
|
||||
MINUTES,
|
||||
/**
|
||||
* Time unit representing one hour.
|
||||
*/
|
||||
HOURS,
|
||||
/**
|
||||
* Time unit representing one day, which always equals 24 hours.
|
||||
*/
|
||||
DAYS;
|
||||
}
|
||||
|
||||
|
||||
public expect fun convertDurationUnit(value: Double, sourceUnit: DurationUnit, targetUnit: DurationUnit): Double
|
||||
|
||||
|
||||
|
||||
internal fun DurationUnit.shortName(): String = when (this) {
|
||||
DurationUnit.NANOSECONDS -> "ns"
|
||||
DurationUnit.MICROSECONDS -> "us"
|
||||
DurationUnit.MILLISECONDS -> "ms"
|
||||
DurationUnit.SECONDS -> "s"
|
||||
DurationUnit.MINUTES -> "m"
|
||||
DurationUnit.HOURS -> "h"
|
||||
DurationUnit.DAYS -> "d"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
public inline fun measureTime(action: () -> Unit): Duration {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return MonoClock.measureTime(action)
|
||||
}
|
||||
|
||||
|
||||
public inline fun Clock.measureTime(action: () -> Unit): Duration {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
|
||||
val mark = mark()
|
||||
action()
|
||||
return mark.elapsedFrom
|
||||
}
|
||||
|
||||
|
||||
|
||||
public data class DurationMeasured<T>(val value: T, val duration: Duration)
|
||||
|
||||
public inline fun <T> withMeasureTime(action: () -> T): DurationMeasured<T> {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
|
||||
return MonoClock.withMeasureTime(action)
|
||||
}
|
||||
|
||||
public inline fun <T> Clock.withMeasureTime(action: () -> T): DurationMeasured<T> {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
|
||||
val mark = mark()
|
||||
val result = action()
|
||||
return DurationMeasured(result, mark.elapsedFrom)
|
||||
}
|
||||
Reference in New Issue
Block a user