Skip to content

Instantly share code, notes, and snippets.

@nomisRev
Created September 21, 2022 07:19
Show Gist options
  • Save nomisRev/e1b5cf39ca4f2931365a1a30f9e0c565 to your computer and use it in GitHub Desktop.
Save nomisRev/e1b5cf39ca4f2931365a1a30f9e0c565 to your computer and use it in GitHub Desktop.
Timed Value monad.
public interface Timed<A> {
public fun result(): A
public fun startMs(): Long
public fun endMs(): Long
}
// Add strategies as needed
public enum class TimedStrategy { EarliestStartAndLatestEnd; }
public interface TimedDSL {
public fun <A> Timed<A>.bind(): A
}
public inline fun <A> timed(
strategy: TimedStrategy = TimedStrategy.EarliestStartAndLatestEnd,
block: TimedDSL.() -> A
): Timed<A> {
val dsl = TimedDSLImpl(strategy, System.currentTimeMillis())
val result = block(dsl)
return TimedValue(
result,
dsl.start.get(),
dsl.end.get() ?: System.currentTimeMillis()
)
}
// We need to make it internal, and publish the API to be able to inline timed so you can also mix it with other _suspend code_.
@PublishedApi
internal data class TimedValue<A>(private val _result: A, private val _startMs: Long, private val _endMs: Long) : Timed<A> {
override fun result(): A = _result
override fun startMs(): Long = _startMs
override fun endMs(): Long = _endMs
}
// We need to make it internal, and publish the API to be able to inline timed so you can also mix it with other _suspend code_.
@PublishedApi
internal class TimedDSLImpl(private val strategy: TimedStrategy, start: Long) : TimedDSL {
// Protect with atomatics, since `inline fun timed` can contain suspend / parallel code.
val start = AtomicRef(start)
val end: AtomicRef<Long?> = AtomicRef(null)
override fun <A> Timed<A>.bind(): A {
when(strategy) {
TimedStrategy.EarliestStartAndLatestEnd -> {
start.update { min(it, startMs()) }
end.update { it?.let { current -> max(current, endMs()) } ?: endMs() }
}
}
return result()
}
}
@nomisRev
Copy link
Author

Code example for a question on KotlinLang Slack. https://kotlinlang.slack.com/archives/C5UPMM0A0/p1663742658572539

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment