2013-04-30 10 views
5

Juste déconner ici, avec des tampons circulaires. Est-ce une mise en œuvre judicieuse ou existe-t-il un moyen plus rapide/plus fiable d'écorcher ce chat?scala collections tampon circulaire

class CircularBuffer[T](size: Int)(implicit mf: Manifest[T]) { 

    private val arr = new scala.collection.mutable.ArrayBuffer[T]() 

    private var cursor = 0 

    val monitor = new ReentrantReadWriteLock() 

    def push(value: T) { 
     monitor.writeLock().lock() 
     try { 
     arr(cursor) = value 
     cursor += 1 
     cursor %= size 
     } finally { 
     monitor.writeLock().unlock() 
     } 
    } 

    def getAll: Array[T] = { 
     monitor.readLock().lock() 
     try { 
     val copy = new Array[T](size) 
     arr.copyToArray(copy) 
     copy 
     } finally { 
     monitor.readLock().unlock() 
     } 
    } 
    } 
+1

Puisque votre tampon est de taille fixe, utilisez un 'Array' comme représentation interne. – gzm0

+1

Vous devriez également jeter un coup d'œil au disrupteur, il s'agit essentiellement d'un tampon circulaire https://github.com/LMAX-Exchange/disruptor – Noah

+0

gzm0, je ne voulais pas allouer tout l'espace, à l'avance. C'est pourquoi j'ai une limite supérieure de taille mais utilise un ArrayBuffer en interne. Est-ce une mauvaise idée? – irishjava

Répondre

3

Création

J'utiliser la déclaration de type et une fonction d'addition à la place « rouler votre propre »:

import scala.collection.immutable 

type CircularBuffer[T] = immutable.Vector[T] 

def emptyCircularBuffer[T] : CircularBuffer[T] = immutable.Vector.empty[T] 

def addToCircularBuffer[T](maxSize : Int)(buffer : CircularBuffer[T], item : T) : CircularBuffer[T] = 
    (buffer :+ item) takeRight maxSize 

Cela signifie que votre « buffer circulaire » est en fait un vecteur et vous maintenant obtenir toutes les méthodes vectorielles correspondantes (filtre, carte, flatMap, etc ...) gratuitement:

var intCircularBuffer = emptyCircularBuffer[Int] 

//Vector(41) 
intCircularBuffer = addToCircularBuffer(2)(intCircularBuffer, 41) 

//Vector(41, 42) 
intCircularBuffer = addToCircularBuffer(2)(intCircularBuffer, 42) 

//Vector(42, 43) 
intCircularBuffer = addToCircularBuffer(2)(intCircularBuffer, 43) 

//Vector(42) 
val evens : CircularBuffer[Int] = intCircularBuffer filter (_ % 2 == 0) 

indexation

Vous pouvez ajouter de la même fonction pour l'indexation circulaire:

def circularIndex[T](buffer : CircularBuffer[T])(index : Int) : T = 
    buffer(index % buffer.size)