Giter Club home page Giter Club logo

cats-stm's People

Contributors

alexandervanhecke avatar armanbilge avatar christopherdavenport avatar dependabot[bot] avatar durban avatar gitter-badger avatar janstenpickle avatar kubukoz avatar lavrov avatar rossabaker avatar scala-steward avatar timwspence avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

cats-stm's Issues

Probable race

Currently we eval stm actions as a criticalSection (under a global lock basically). This shouldn't be necessary and I've never produced a test that fails but if we don't do this then the Santa Claus example stops producing output after a few seconds. My best guess is that we don't update fibers to be retried correctly (either we forget about them or we fail to register them for retry in time). The alternative is that it is deadlock simply because we have too many threads contenting for a lock on STM. So it would be nice to fix #168 first to see if this issue magically goes away.

santa claus example on github.io does not compile

Hi, thanks for the library !

I was going through the tutorial, but the code published on github.io does not compile.

If you copy the code directly from https://github.com/TimWSpence/cats-stm/blob/master/docs/docs/tutorial/tutorial.md it works just fine, but it seems the publish process to github.io gets confused by the ; instances in the code.

This :

}; object Gate{

somehow gets translated to

}; object Gate{; object Gate{

on github.io

I'm guessing getting rid of the ; and putting the companion object on a separate line will fix the issue.

Let me know if you'd like me to submit a PR, I'm happy to do so.

Better critical sections

Currently out critical sections are implemented using blocker.blockOn(F.delay(STM.synchronized{...})) which sucks. It also means we have to statically allocate a Blocker backed by a daemon threadpool. Which sucks. It might well also be to blame for #164. Which sucks.

It would be nice to move to cats effect non-thread-blocking concurrency primitives. However, we can't statically allocate these as we don't know what the concrete monad will be. The only solution I can think of right now is to add an implicit runtime: STMRuntime to atomically. This might look something like:

trait STMRuntime[F[_]] {
  val globalLock: Semaphore[F]
}

but I'd love to hear other suggestions!

Publish with Java 8

I've been building and publishing with Java 11. It turns out this is a bad idea.

Possibly a case of adding

  .jvmSettings(
    javacOptions ++= Seq("-source", "1.8", "-target", "1.8")
  )

to build.sbt

Optimization

We currently store a List[Deferred[F, Unit]] in every TVar to signal transactions that are blocked on that TVar. Is it possible to just store a single Deferred[F, Unit] instead and have all txns block on that Deferred being completed?

Help !

Hi,

I can't find a lot of documentation or post online about this module of cats which i find amazing. Where can i find good material to learn from it.

I have a use case where i am relying on a very old Java api, which is all about mutation. I want to isolate it and get back a sense of referential transparency. The all api, is all about mutating value. It is an api to mange RDF model.

Hence I was thinking about finding an abstraction other than just IO, which would help me write some good referentially transparent code and track the mutation

any advise ?

(Lack of) opacity

Opacity is a correctness property for STM algorithms. Here is a short description and pointers to more reading: https://nbronson.github.io/scala-stm/semantics.html#opacity. The really short version is that opacity guarantees that a running transaction will never read inconsistent values from transactional varables, even if that transaction will never commit or fail.

It seems that currently cats-stm does not provide opacity. We can see this with the following example: let's have two TVar[Int]s, r1 and r2, with the invariant that r1 < r2. One transaction increments the values (transactionally), upholding this invariant:

  def txn1(r1: TVar[Int], r2: TVar[Int]): Txn[Unit] = {
    r1.modify(_ + 1) *> r2.modify(_ + 1)
  }

Another transaction reads from both TVars, and compares the values; if it reads impossible (inconsistent) values, it prints ERROR: ...:

  def txn2(r1: TVar[Int], r2: TVar[Int]): Txn[Int] = {
    r1.get.flatMap { v1 =>
      r2.get.map { v2 =>
        if (v2 <= v1) {
          println(s"ERROR: (${v1}, ${v2})")
        }
        v2 - v1
      }
    }
  }

Sometimes when txn1 and txn2 run concurrently, txn2 can observe the impossible (inconsistent) values (see below for a full reproduction). Such running instances of txn2 seem to not commit/fail (they seem to be retried). However, observing such inconsistency in a running transaction can still be problematic; for example, we could have while (true) {} instead of println(...), which would cause the transaction to never commit or fail.

Full code example:

package com.example

import cats.effect.kernel.Concurrent
import cats.effect.IO
import cats.syntax.all._

import io.github.timwspence.cats.stm.STM

import munit.CatsEffectSuite

class StmExample[F[_]](stm: STM[F])(implicit F: Concurrent[F]) {

  import stm._

  private[this] def txn1(r1: TVar[Int], r2: TVar[Int]): Txn[Unit] = {
    r1.modify(_ + 1) *> r2.modify(_ + 1)
  }

  private[this] def txn2(r1: TVar[Int], r2: TVar[Int]): Txn[Int] = {
    r1.get.flatMap { v1 =>
      r2.get.map { v2 =>
        if (v2 <= v1) {
          println(s"ERROR: (${v1}, ${v2})")
        }
        v2 - v1
      }
    }
  }

  def example: F[Int] = for {
    r1 <- stm.commit(TVar.of(0))
    r2 <- stm.commit(TVar.of(1))
    t1 = stm.commit(txn1(r1, r2))
    t2 = F.parReplicateAN(32)(
      replicas = 64,
      ma = stm.commit(txn2(r1, r2)).flatTap {
        case 1 => F.unit
        case x => F.raiseError[Unit](new Exception(s"result was $x"))
      }
    )
    b = F.both(F.cede *> t1, F.cede *> t2)
    r <- b.replicateA(8192).map(_.last._2)
  } yield r.last
}

final class CatsStmTest extends CatsEffectSuite {

  test("Test STM") {
    STM.Make[IO].runtime(Long.MaxValue).flatMap { stm =>
      assertIO(new StmExample[IO](stm).example, 1)
    }
  }
}

Running this test results in output like this:

ERROR: (1388, 1388)
ERROR: (1388, 1388)
ERROR: (1388, 1388)
ERROR: (2205, 2205)
ERROR: (2205, 2205)

(The number of ERROR lines is non-deterministic, sometimes even zero.)

Retry is not fair

The current behaviour (which is expected but not desired) is that retry is biased in favour of newer transactions, leading to the risk of starvation for older transactions. You can see this in action with the santa claus problem, where the behaviour stabilises on only running the reindeer transactions.

This is because every time a transaction T succeeds, it picks up any transactions which are new candidates for retry and clears the pending state. If any of these retried transactions T1 succeed, they will do the same thing and hence the other transactions being retried by T will effectively go to the "back of the line", behind those being retried by T1 and so on.

I'm documenting this behaviour here both as a reminder to myself and in case anyone else sees this first and feels like fixing it before I get round to it!

Instantiating Class which requires a TVar

Hello

Having upgraded from 0.8.0 to 0.11.0 I have what is either a question or an issue (I am unsure but raising it as an issue to hopefully at least get an answer).

I have a class that requires a TVar to be passed in at instantiation which is posing an import based issue.

class MyClass(val stuff: TVar[String]) { ... }

Previously (0.8.0) I could have an "import io.github.timwspence.cats.stm.TVar" at the top of my class, this no longer works and from the examples the approach is something akin to

val stm = STM.runtime[IO].unsafeRunSync()
import stm._

but this does not work outside of a class or object?
Is there a way to reference the TVar class without having to instatiate the Stm Runtime?

Please advise if this is a legitimate issue, a misuse issue or just a misunderstanding?
Karl

TDeferred

Would be nice to have a TDeferred

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.