package gs.timing.v0 import cats.Functor import cats.syntax.all.* import java.util.concurrent.TimeUnit import scala.concurrent.duration.FiniteDuration /** Timer based on monotonic time expressed as nanoseconds. Each timer is based * on a fixed start point, and calculates [[ElapsedTime]] based on that point. * * This class should be instantiated by [[Timing]], which will inject an * appropriate function for calculating elapsed time. * * ## Usage * * {{{ * import gs.timing.v0.Timing * import cats.effect.IO * * val timing = Timing.system[IO] * * val program: IO[List[ElapsedTime]] = * for * timer <- timing.start() * elapsed1 <- timer.checkpoint() * elapsed2 <- timer.checkpoint() * elapsed3 <- timer.checkpoint() * yield * List(elapsed1, elapsed2, elapsed3) * }}} * * @param start * The fixed start point, expressed as monotonic time (nanoseconds, tick * count). * @param checkpointFunction * The checkpoint function used to evaluate the current time. */ final class MonotonicTimer[F[_]: Functor]( val start: Long, private val checkpointFunction: () => F[Long] ): /** @return * The [[ElapsedTime]] (in nanoseconds) based on the fixed start point and * checking the current monotonic time. */ def checkpoint(): F[ElapsedTime] = checkpointFunction().map(end => ElapsedTime( start = start, end = end, duration = new FiniteDuration(end - start, TimeUnit.NANOSECONDS) ) )