MVar tryPut-true和isEmpty也为true

问题描述 投票:0回答:1

我编写了简单的callback(handler)函数,该函数传递给异步api,我想等待结果:

object Handlers {

  val logger: Logger = Logger("Handlers")
  implicit val cs: ContextShift[IO] =
  IO.contextShift(ExecutionContext.Implicits.global)

  class DefaultHandler[A] {

  val response: IO[MVar[IO, A]] = MVar.empty[IO, A]

  def onResult(obj: Any): Unit = {
    obj match {
      case obj: A =>
        println(response.flatMap(_.tryPut(obj)).unsafeRunSync())
        println(response.flatMap(_.isEmpty).unsafeRunSync())
      case _ => logger.error("Wrong expected type")
    }
  }

  def getResponse: A = {
    response.flatMap(_.take).unsafeRunSync()
  }
}

但是由于某些原因,tryPut和isEmpty(当我手动调用onResult方法时)都返回true,因此,当我调用getResponse时,它将永远休眠。这是我的测试:

class HandlersTest extends FunSuite {
    test("DefaultHandler.test") {
    val handler = new DefaultHandler[Int]
    handler.onResult(3)
    val response = handler.getResponse
    assert(response != 0)
    }
  }

有人可以解释为什么tryPut返回true,但是没有放入。在scala中使用Mvar /通道的正确方法是什么?

scala concurrency scala-cats side-effects
1个回答
0
投票

IO[X]表示您具有创建某些X的配方。因此,在您的示例中,yuo正在放入一个MVar,然后再询问另一个。

这是我要怎么做。

object Handlers {
  trait DefaultHandler[A] {
    def onResult(obj: Any): IO[Unit]

    def getResponse: IO[A]
  }

  object DefaultHandler {
    def apply[A : ClassTag]: IO[DefaultHandler[A]] = 
      MVar.empty[IO, A].map { response =>
        new DefaultHandler[A] {
          override def onResult(obj: Any): IO[Unit] = obj match {
              case obj: A =>
                for {
                  r1 <- response.tryPut(obj)
                  _  <- IO(println(r1))
                  r2 <- response.isEmpty
                  _  <- IO(println(r2))
                } yield ()

              case _ =>
                IO(logger.error("Wrong expected type"))
            }

          override def getResponse: IO[A] =
            response.take
        }
      }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.