Skip to main content
Added a get method to avoid unsafe access to the whole map from outside.
Source Link
Mushtaq Ahmed
  • 6.4k
  • 2
  • 19
  • 14

If you are ok to work with future based interface:

trait SingleThreadedExecutionContext {
  val ec = ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor())
}

class Counter extends SingleThreadedExecutionContext {
  private val counts = MMap.empty[String, Int].withDefaultValue(0)
  
  def get(s: String): Future[Int] = future(counts(s))(ec)

  def add(s: String): Future[Unit] = future(counts(s) += 1)(ec)
}

Test will look like:

class MutableMapSpec extends Specification {

  "thread safe" in {

    import ExecutionContext.Implicits.global

    val c = new Counter
    val testData = Seq.fill(16)("1")
    await(Future.traverse(testData)(c.add))
    await(c.counts mustEqual MMapget("1")) ->mustEqual 16)
  }
}

If you are ok to work with future based interface:

trait SingleThreadedExecutionContext {
  val ec = ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor())
}

class Counter extends SingleThreadedExecutionContext {
  val counts = MMap.empty[String, Int].withDefaultValue(0)

  def add(s: String): Future[Unit] = future(counts(s) += 1)(ec)
}

Test will look like:

class MutableMapSpec extends Specification {

  "thread safe" in {

    import ExecutionContext.Implicits.global

    val c = new Counter
    val testData = Seq.fill(16)("1")
    await(Future.traverse(testData)(c.add))
    c.counts mustEqual MMap("1" -> 16)
  }
}

If you are ok to work with future based interface:

trait SingleThreadedExecutionContext {
  val ec = ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor())
}

class Counter extends SingleThreadedExecutionContext {
  private val counts = MMap.empty[String, Int].withDefaultValue(0)
  
  def get(s: String): Future[Int] = future(counts(s))(ec)

  def add(s: String): Future[Unit] = future(counts(s) += 1)(ec)
}

Test will look like:

class MutableMapSpec extends Specification {

  "thread safe" in {

    import ExecutionContext.Implicits.global

    val c = new Counter
    val testData = Seq.fill(16)("1")
    await(Future.traverse(testData)(c.add))
    await(c.get("1")) mustEqual 16
  }
}
Source Link
Mushtaq Ahmed
  • 6.4k
  • 2
  • 19
  • 14

If you are ok to work with future based interface:

trait SingleThreadedExecutionContext {
  val ec = ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor())
}

class Counter extends SingleThreadedExecutionContext {
  val counts = MMap.empty[String, Int].withDefaultValue(0)

  def add(s: String): Future[Unit] = future(counts(s) += 1)(ec)
}

Test will look like:

class MutableMapSpec extends Specification {

  "thread safe" in {

    import ExecutionContext.Implicits.global

    val c = new Counter
    val testData = Seq.fill(16)("1")
    await(Future.traverse(testData)(c.add))
    c.counts mustEqual MMap("1" -> 16)
  }
}