All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twitter.finagle.util.Updater.scala Maven / Gradle / Ivy

package com.twitter.finagle.util

import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.ConcurrentLinkedQueue
import scala.collection.mutable.ArrayBuffer

/**
 * An Updater processes updates in sequence. At most one one
 * update is processed at time; pending updates may be collapsed.
 * 
 * When an update is in progress, new updates are enqueued to 
 * be handled by the thread currently processing updates; the
 * control is returned to the caller thread immediately. Thus
 * the thread issuing the first update will process all updates 
 * until the queue of updates has been drained.
 *
 * Fairness is not guaranteed. Provided a sufficiently high rate of
 * updates, the hapless handler thread may be stuck with the job
 * indefinitely.
 */
private[finagle] trait Updater[T] extends (T => Unit) {
  private[this] val n = new AtomicInteger(0)
  private[this] val q = new ConcurrentLinkedQueue[T]
  
  /**
   * Preprocess a nonempty batch of updates. This allows the updater
   * to collapse, expand, or otherwise manipulate updates before they
   * are handled.
   */
  protected def preprocess(elems: Seq[T]): Seq[T]

  /**
   * Handle a single update.
   */
  protected def handle(elem: T): Unit

  def apply(t: T) {
    q.offer(t)
    if (n.getAndIncrement() > 0)
      return

    do {
      val elems = new ArrayBuffer[T](1+n.get)
      while (n.get > 1) {
        n.decrementAndGet()
        elems += q.poll()
      }

      elems += q.poll()

      for (elem <- preprocess(elems.result))
        handle(elem)
    } while (n.decrementAndGet() > 0)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy