Skip to content

Instantly share code, notes, and snippets.

@mikemckibben
Created December 18, 2012 17:59
Show Gist options
  • Save mikemckibben/4330378 to your computer and use it in GitHub Desktop.
Save mikemckibben/4330378 to your computer and use it in GitHub Desktop.
lazy, resetable atomic reference
class ManagedReference[T](private[this] val createF: => T, private[this] val closeF: Option[T => Unit] = None) {
import java.util.concurrent.atomic.{ AtomicReference }
private[this] val ref = new AtomicReference[Option[T]](None)
def apply(): T = {
val opt = ref.get
val value = opt.getOrElse(createF)
// test if ref was set by another thread between ref.get and opt.getOrElse
if (ref.compareAndSet(opt, opt.orElse(Some(value))))
value
else {
// close
closeF.foreach(_(value))
apply()
}
}
def reset(): Unit = ref.getAndSet(None).foreach(t => closeF.foreach(_(t)))
override protected def finalize(): Unit = {
try {
reset()
} catch {
// guard against exceptions thrown during finalize
case _ : Throwable =>
}
}
}
object ManagedReference {
import java.io.{ Closeable }
def apply[A](createF: => A): ManagedReference[A] = new ManagedReference[A](createF)
def apply[A](createF: => A, closeF: A => Unit): ManagedReference[A] = new ManagedReference[A](createF, Some(closeF))
def apply[A <: Closeable](ref: A): ManagedReference[A] = new ManagedReference[A](ref, Some(_.close()))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment