package sbt package inc import java.io.File import java.util.concurrent.ConcurrentHashMap sealed trait FileValueCache[T] { def clear(): Unit def get: File => T } private[this] final class FileValueCache0[T](getStamp: File => Stamp, make: File => T)(implicit equiv: Equiv[Stamp]) extends FileValueCache[T] { private[this] val backing = new ConcurrentHashMap[File, FileCache] def clear(): Unit = backing.clear() def get = file => { val ifAbsent = new FileCache(file) val cache = backing.putIfAbsent(file, ifAbsent) (if(cache eq null) ifAbsent else cache).get() } private[this] final class FileCache(file: File) { private[this] var stampedValue: Option[(Stamp,T)] = None def get(): T = synchronized { val latest = getStamp(file) stampedValue match { case Some( (stamp, value) ) if(equiv.equiv(latest, stamp)) => value case _ => update(latest) } } private[this] def update(stamp: Stamp): T = { val value = make(file) stampedValue = Some((stamp, value)) value } } } object FileValueCache { def apply[T](f: File => T): FileValueCache[T] = make(Stamp.lastModified)(f) def make[T](stamp: File => Stamp)(f: File => T): FileValueCache[T] = new FileValueCache0[T](stamp, f) }