Cats STM

Build Status Join the chat at https://gitter.im/cats-stm/community

An implementation of Software Transactional Memory for Cats Effect, inspired by Beautiful Concurrency.

For more information, see the documentation.

Usage

libraryDependencies += "io.github.timwspence" %% "cats-stm" % "0.3.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.

import cats.effect.{ExitCode, IO, IOApp}
import io.github.timwspence.cats.stm.{TVar, STM}

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] = for {
    _ <- STM.atomically[IO] {
      for {
        balance <- accountForTim.get
        _       <- STM.check(balance > 100)
        _       <- accountForTim.modify(_ - 100)
        _       <- accountForSteve.modify(_ + 100)
      } yield ()
    }
  } yield ()

  private def giveTimMoreMoney(accountForTim: TVar[Long]): IO[Unit] = for {
    _ <- IO(Thread.sleep(5000))
    _ <- STM.atomically[IO](accountForTim.modify(_ + 1))
  } yield ()

  private def printBalances(accountForTim: TVar[Long], accountForSteve: TVar[Long]): IO[Unit] = for {
    _ <- accountForTim.get.commit[IO].flatMap(b => IO(println(s"Tim: $b")))
    _ <- accountForSteve.get.commit[IO].flatMap(b => IO(println(s"Tim: $b")))
  } yield ()

}

Documentation

The documentation is built using sbt microsites. You can generate it via sbt makeMicrosite. You can view it locally via cd docs/target/site && jekyll serve.