类型类模式:找不到模拟增强方法

时间:2018-11-25 23:45:37

标签: scala intellij-idea implicit-conversion typeclass simulacrum

我要求能够计算在类中具有字段通配符原子引用数组的类中调用AtomicReference[V].get的次数。

为此,首先,我扩展了Java的AtomicReference [V]:

import java.util.concurrent.atomic.{AtomicInteger => AInt, AtomicReference => ARef}

class MyAtomicReference[V] extends ARef[V]{

  private val getCounter: AInt = new AInt(0)

  def getAndListen(): V = {
    getCounter.getAndIncrement()
    super.get()
  }

  def counter(): Int = getCounter.get()

  def resetCounter(): Unit = getCounter.set(0)
}

然后我添加了特征AtomicRefCounter,该特征声明了我希望调用的方法:

import simulacrum.typeclass

 @typeclass trait AtomicRefCounter [R[_], T] {
  def countGets(container: R[T]): Int
}

最后,我在对象AtomicArrayRefCounter中定义了默认的DefaultAtomicRefCounters

object DefaultAtomicRefCounters {

  implicit val arrayOfAtomicsTraverser = new AtomicRefCounter[Array, MyAtomicReference[_]] {
    override def countGets(container: Array[MyAtomicReference[_]]): Int = container map(_.counter()) sum
  }
}

尽管当我尝试在测试中的相应数组上调用traverseAtomics()时,却看不到它(我正在使用Intellij IDEA):

behavior of "removeO1"

  "method" should "remove an element from the pool with time O(1)" in new IntPoolBuilder {
    import org.learningconcurrency.traditional_concurrency.helpers.DefaultAtomicRefCounters._
pool.buckets.countGet
      }

就我所缺少的内容提供一些建议确实会有所帮助。 simulacrum的使用不是强制性的-如果您认为不知道如何解决此问题,我很想听听。

更新

这是实现buckets的方式:

class Pool[T] {

  type TimeStampedList = (List[T], Long)

  val parallelism: Int = Runtime.getRuntime.availableProcessors * 32
  val buckets = new Array[MyAtomicReference[TimeStampedList]](parallelism)
...

2 个答案:

答案 0 :(得分:2)

我认为,您可能会错理解隐含的工作方式。

如果我正确阅读了所有内容,则输入您的代码

implicitly[AtomicRefCounter[Array, MyAtomicReference[_]]].countGets(pool.buckets)

应该工作。

如果您想在countGets上致电Array,则应使用 EnrichMyLibrary 模式。

object DefaultAtomicRefCounters {
  implicit class RichArray(private underlying: Array[MyAtomicReference[_]] extends AnyVal {
    def countGets: Int = underlying.map(_.counter()).sum
  }
}

答案 1 :(得分:0)

令人失望的是,我无法使其与模拟注释一起使用,因此我遵循了Sascha的建议。我只是稍微修改了他的第二个示例(我无法使其与implictly一起使用),因此它可以编译并正常工作:

object TraditionalConcurrencyHelpers {
  implicit class CountArrayAtomicGetsOps(wrapper: Array[MyAtomicReference[(List[Int], Long)]]) {
    def countGets()(implicit atomicRefCounter: AtomicRefCounter[Array, MyAtomicReference[(List[Int], Long)]]): Int = atomicRefCounter.countGets(wrapper)
  }
}

有了这个,我可以在数组上调用countGets了:

  behavior of "removeO1"

  "method" should "remove an element from the pool with time O(1)" in new IntPoolBuilder {
    import TraditionalConcurrencyHelpers._
    import org.learningconcurrency.traditional_concurrency.helpers.DefaultAtomicRefCounters._
    //call pool.removeO1 (not implemented yet)
    pool.buckets.countGets() shouldEqual 1
  }