Skip to content

Instantly share code, notes, and snippets.

@t3hnar
Created January 14, 2019 16:00
Show Gist options
  • Save t3hnar/b4229b27d643c22637d2135fa6b053e5 to your computer and use it in GitHub Desktop.
Save t3hnar/b4229b27d643c22637d2135fa6b053e5 to your computer and use it in GitHub Desktop.
import cats.effect.Concurrent
import cats.effect.concurrent.{Deferred, Ref}
import cats.implicits._
trait Cache[F[_], K, V] {
def getOrUpdate(k: K)(v: F[V]): F[V]
def values: F[Map[K, Deferred[F, V]]]
}
object Cache {
def of[F[_] : Concurrent, K, V]: F[Cache[F, K, V]] = {
for {
ref <- Ref.of[F, Map[K, Deferred[F, V]]](Map.empty)
} yield {
new Cache[F, K, V] {
// TODO add support of cancellation
def getOrUpdate(k: K)(v: F[V]) = {
for {
map <- ref.get
v <- map.get(k).fold {
for {
d <- Deferred[F, V]
v <- ref.modify { map =>
map.get(k).fold {
val value = for {
v <- v
_ <- d.complete(v)
} yield v
(map.updated(k, d), value)
} { d =>
(map, d.get)
}
}
v <- v
} yield {
v
}
} { d =>
d.get
}
} yield {
v
}
}
def values = ref.get
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment