Tuesday, 6 March 2012

Atomic update of AtomicReference

Problem

I like the AtomicReference class. When used with a immutable class, it offers quite a nice and efficient abstraction for concurrent data structure. One thing it is missing, in my opinion, is the atomic update method, ie.
  val list = new AtomicReference(List(1,2,3))
  list.update(list => list.map(_ *2))

Solution

You just need to import the Atomic class, and it will pimp the AtomicReference, so you can call the update method. See below:
import annotation.tailrec
import java.util.concurrent.atomic.AtomicReference
object Atomic {
def apply[T]( obj : T) = new Atomic(new AtomicReference(obj))
implicit def toAtomic[T]( ref : AtomicReference[T]) : Atomic[T] = new Atomic(ref)
}
class Atomic[T](val atomic : AtomicReference[T]) {
@tailrec
final def update(f: T => T) : T = {
val oldValue = atomic.get()
val newValue = f(oldValue)
if (atomic.compareAndSet(oldValue, newValue)) newValue else update(f)
}
def get() = atomic.get()
}
view raw gistfile1.scala hosted with ❤ by GitHub
Enjoy!