scala.rx icon indicating copy to clipboard operation
scala.rx copied to clipboard

Leaking without compile error

Open Semptic opened this issue 8 years ago • 3 comments

Moving the example from the Readme into a class without adding an explicit owner in mkRx leads to an leak. and no compiler error helps you to avoid this.

The class:

class Test(implicit ctx: Ctx.Owner) {
    var count = 0
    val a = Var(1); val b = Var(2)
    def mkRx(i: Int) = Rx { count += 1; i + b() }
    val c = Rx {
      val newRx = mkRx(a())
      newRx()
    }
    println(c.now, count)
    a() = 4
    println(c.now, count)
    b() = 3
    println(c.now, count) //(7,5) -- 5??

    (0 to 100).foreach { i => a() = i }
    println(c.now, count)
    b() = 4
    println(c.now, count) //(104,211) -- 211!!!
  }

I don't know if there is a way to handle this or it's known issue, but I thought it should be mentioned.

Semptic avatar May 31 '16 19:05 Semptic

I've run the example using:

    import rx.Ctx.Owner.Unsafe._
    new Test()

and the results is as in comments: println(c.now, count) //(104,211) -- 211!!!. Am I running it in wrong way?

scalaRxVersion = "0.3.1"

pawelpanasewicz avatar Sep 29 '16 12:09 pawelpanasewicz

After changing Owner.Unsafe to Ctx.Owner.safe() it works in the same way

    class Test {
      implicit val ctx: Ctx.Owner = Ctx.Owner.safe()

      var count = 0
      val a = Var(1); val b = Var(2)
...
new Test()

pawelpanasewicz avatar Sep 29 '16 17:09 pawelpanasewicz

For Future reference, the code should look like this in order to work correctly:

class Test(implicit ctx: Ctx.Owner) {
    var count = 0
    val a = Var(1); val b = Var(2)
    // we need to pass the implicit ctx! Alternative you can only pass ctx.Data.
    def mkRx(i: Int)(implicit ctx: Ctx.Owner) = Rx { count += 1; i + b() }
    val c = Rx {
      // calls mkRx with the owner of the current Rx-Trigger, will be killed on next trigger
      val newRx = mkRx(a()) 
      newRx()
    }
    println(c.now, count)
    a() = 4
    println(c.now, count)
    b() = 3
    println(c.now, count) //(7,5) -- 5??

    (0 to 100).foreach { i => a() = i }
    println(c.now, count)
    b() = 4
    println(c.now, count) //(104,211) -- 211!!!
  }

I think, this issue can be closed. The general problem of lacking documentation is tracked here: #67

cornerman avatar Oct 04 '19 17:10 cornerman