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.8.0"
The core abstraction is the TVar
(transactional var), which exposes operations in the
Txn
monad. Once constructed, Txn
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 scala.concurrent.duration._
import cats.effect.unsafe.implicits.global
import cats.effect.{IO, IOApp}
object Main extends IOApp.Simple {
val stm = STM.runtime[IO].unsafeRunSync()
import stm._
override def run: IO[Unit] =
for {
accountForTim <- stm.commit(TVar.of[Long](100))
accountForSteve <- stm.commit(TVar.of[Long](0))
_ <- printBalances(accountForTim, accountForSteve)
_ <- giveTimMoreMoney(accountForTim).start
_ <- transfer(accountForTim, accountForSteve)
_ <- printBalances(accountForTim, accountForSteve)
} yield ()
private def transfer(accountForTim: TVar[Long], accountForSteve: TVar[Long]): IO[Unit] =
stm.commit {
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.commit(accountForTim.modify(_ + 1))
} yield ()
private def printBalances(accountForTim: TVar[Long], accountForSteve: TVar[Long]): IO[Unit] =
for {
(amountForTim, amountForSteve) <- stm.commit(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 docusaurus. You can
generate it via nix-shell --run "sbt docs/docusaurusCreateSite"
. You can then
view it via nix-shell --run "cd website && npm start"
.
This software was inspired by Beautiful Concurrency and the stm package.
Many thanks to @impurepics for the awesome logo!
Development of Cats STM is generously supported in part by YourKit through the use of their excellent Java profiler.