Типовая модель класса: не найден метод, ускоряющий симулякр - PullRequest
0 голосов
/ 26 ноября 2018

У меня есть требование, чтобы иметь возможность подсчитывать количество раз AtomicReference[V].get вызывается в классе, который имеет в качестве поля массив подстановочных атомных ссылок.

Для этого, во-первых, я расширил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ИДЕЯ):

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 не является обязательным - если вы чувствуете, что знаете, как решить эту проблему без него, я хотел бы услышать это.

update :

Вот как реализовано 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 голосов
/ 27 ноября 2018

Несмотря на разочарование, я не мог заставить его работать с аннотацией к симулякру, поэтому я последовал совету Саши.Я просто немного изменил его второй пример (я не смог заставить его работать с 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
  }
0 голосов
/ 26 ноября 2018

Я думаю, вы, возможно, ошиблись, как влияет на работу.

Если я все правильно прочитал, то в вашем коде

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
  }
}
...