Cleaning up tasks and caching

This commit is contained in:
Mark Harrah 2009-12-11 18:56:09 -05:00
parent 4bd6f9627b
commit 604a5413c9
6 changed files with 56 additions and 31 deletions

29
cache/Cache.scala vendored
View File

@ -23,18 +23,23 @@ object Cache extends BasicCacheImplicits with SBinaryFormats with HListCacheImpl
def wrapOutputCache[O,DO](implicit convert: O => DO, reverse: DO => O, base: OutputCache[DO]): OutputCache[O] =
new WrappedOutputCache[O,DO](convert, reverse, base)
/* Note: Task[O] { type Input = I } is written out because ITask[I,O] did not work (type could not be inferred properly) with a task
* with an HList input.*/
def apply[I,O](task: Task[O] { type Input = I }, file: File)(implicit cache: Cache[I,O]): Task[O] { type Input = I } =
task match { case m: M[I,O,_] =>
new M[I,O,Result[O]](None)(m.dependencies)(m.extract)(computeWithCache(m, cache, file))
}
private def computeWithCache[I,O](m: M[I,O,_], cache: Cache[I,O], file: File)(in: I): Result[O] =
cache(file)(in) match
{
case Left(value) => Value(value)
case Right(store) => m.map { out => store(out); out }
}
def apply[I,O](file: File)(f: I => Task[O])(implicit cache: Cache[I,O]): I => Task[O] =
in =>
cache(file)(in) match
{
case Left(value) => Task(value)
case Right(store) => f(in) map { out => store(out); out }
}
def cached[I,O](file: File)(f: I => O)(implicit cache: Cache[I,O]): I => O =
in =>
cache(file)(in) match
{
case Left(value) => value
case Right(store) =>
val out = f(in)
store(out)
out
}
}
trait BasicCacheImplicits extends NotNull
{

View File

@ -1,18 +1,18 @@
package xsbt
import java.io.{InputStream,OutputStream}
import metascala.HLists.{HCons,HList,HNil}
import HLists._
class HNilInputCache extends NoInputCache[HNil]
class HConsInputCache[H,T <: HList](val headCache: InputCache[H], val tailCache: InputCache[T]) extends InputCache[HCons[H,T]]
{
def uptodate(in: HCons[H,T])(cacheStream: InputStream) =
{
lazy val headResult = headCache.uptodate(in.head)(cacheStream)
lazy val tailResult = tailCache.uptodate(in.tail)(cacheStream)
val headResult = headCache.uptodate(in.head)(cacheStream)
val tailResult = tailCache.uptodate(in.tail)(cacheStream)
new CacheResult
{
lazy val uptodate = headResult.uptodate && tailResult.uptodate
val uptodate = headResult.uptodate && tailResult.uptodate
def update(outputStream: OutputStream) =
{
headResult.update(outputStream)

View File

@ -4,19 +4,25 @@ import java.io.File
object CacheTest// extends Properties("Cache test")
{
val lengthCache = new File("/tmp/length-cache")
val cCache = new File("/tmp/c-cache")
import Task._
import Cache._
import FileInfo.hash._
def checkFormattable(file: File)
def test
{
val createTask = Task { new File("test") }
val lengthTask = createTask map { f => println("File length: " + f.length); f.length }
val cached = Cache(lengthTask, new File("/tmp/length-cache"))
val cTask = (createTask :: cached :: TNil) map { case (file :: len :: HNil) => println("File: " + file + " length: " + len); len :: file :: HNil }
val cachedC = Cache(cTask, new File("/tmp/c-cache"))
val length = (f: File) => { println("File length: " + f.length); f.length }
val cachedLength = cached(lengthCache) ( length )
try { TaskRunner(cachedC) }
val lengthTask = createTask map cachedLength
val c = (file: File, len: Long) => { println("File: " + file + ", length: " + len); len :: file :: HNil }
val cTask = (createTask :: lengthTask :: TNil) map cached(cCache) { case (file :: len :: HNil) => c(file, len) }
try { TaskRunner(cTask) }
catch { case TasksFailed(failures) => failures.foreach(_.exception.printStackTrace) }
}
}

View File

@ -24,7 +24,7 @@ class Changed[O](val task: Task[O], val cacheFile: File)(implicit input: InputCa
{
val clean = Clean(cacheFile)
def clear = Task.empty
def apply[O2](ifChanged: O => O2, ifUnchanged: O => O2): Task[O2] { type Input = O } =
def apply[O2](ifChanged: O => O2, ifUnchanged: O => O2): Task[O2] =
task map { value =>
val cache =
try { OpenResource.fileInputStream(cacheFile)(input.uptodate(value)) }

View File

@ -1,15 +1,29 @@
package xsbt
import metascala.HLists.{HCons => metaHCons, HList => metaHList, HNil => metaHNil}
// stripped down version of http://trac.assembla.com/metascala/browser/src/metascala/HLists.scala
// Copyright (c) 2009, Jesper Nordenberg
// new BSD license, see licenses/MetaScala
object HLists extends HLists
// add an extractor to metascala.HLists and define aliases to the HList classes in the xsbt namespace
trait HLists extends NotNull
trait HLists
{
object :: { def unapply[H,T<:HList](list: HCons[H,T]) = Some((list.head,list.tail)) }
final val HNil = metaHNil
final type ::[H, T <: HList] = metaHCons[H, T]
final type HNil = metaHNil
final type HList = metaHList
final type HCons[H, T <: HList] = metaHCons[H, T]
type ::[H, T <: HList] = HCons[H, T]
}
object HNil extends HNil
sealed trait HList {
type Head
type Tail <: HList
}
sealed class HNil extends HList {
type Head = Nothing
type Tail = HNil
def ::[T](v : T) = HCons(v, this)
}
final case class HCons[H, T <: HList](head : H, tail : T) extends HList {
type Head = H
type Tail = T
def ::[T](v : T) = HCons(v, this)
}