An implementation of Software Transactional Memory for Cats Effect, inspired by Beautiful Concurrency.
For more information, see the documentation.
libraryDependencies += "io.github.timwspence" %% "cats-stm" % "0.7.0"
The core abstraction is the TVar
(transactional var), which exposes operations in the
STM
monad. Once constructed, STM
actions can be atomically evaluated in the IO
monad.
Here is a contrived example of what this looks like in practice. We use the
check
combinator to retry transferring money from Tim and Steve until we have
enough money in Tim's account:
import cats.effect.{ExitCode, IO, IOApp}
import io.github.timwspence.cats.stm.{TVar, STM}
import scala.concurrent.duration._
object Main extends IOApp {
override def run(args: List[String]): IO[ExitCode] =
for {
accountForTim <- TVar.of[Long](100).commit[IO]
accountForSteve <- TVar.of[Long](0).commit[IO]
_ <- printBalances(accountForTim, accountForSteve)
_ <- giveTimMoreMoney(accountForTim).start
_ <- transfer(accountForTim, accountForSteve)
_ <- printBalances(accountForTim, accountForSteve)
} yield ExitCode.Success
private def transfer(accountForTim: TVar[Long], accountForSteve: TVar[Long]): IO[Unit] =
STM.atomically[IO] {
for {
balance <- accountForTim.get
_ <- STM.check(balance > 100)
_ <- accountForTim.modify(_ - 100)
_ <- accountForSteve.modify(_ + 100)
} yield ()
}
private def giveTimMoreMoney(accountForTim: TVar[Long]): IO[Unit] =
for {
_ <- IO.sleep(5000.millis)
_ <- STM.atomically[IO](accountForTim.modify(_ + 1))
} yield ()
private def printBalances(accountForTim: TVar[Long], accountForSteve: TVar[Long]): IO[Unit] =
for {
(amountForTim, amountForSteve) <- STM.atomically[IO](for {
t <- accountForTim.get
s <- accountForSteve.get
} yield (t, s))
_ <- IO(println(s"Tim: $amountForTim"))
_ <- IO(println(s"Steve: $amountForSteve"))
} yield ()
}
The documentation is built using sbt microsites. You
can generate it via sbt docs/makeMicrosite
. You can view it locally via cd docs/target/site && jekyll serve
.
This software was inspired by Beautiful Concurrency and informed by ZIO which has a common origin in that paper via the stm package.