Exercise7.3 map2を修正し、Futureのタイムアウトの規約に従うようにせよ。
javaをよく理解してなこともあり、コードを読み取るのが難しい。
Map2Futureの中にある@volatileは、「あるスレッドで更新された値が別スレッドで読み込まれる」ことが保証されるのだそうだ。
chache.isDefinedはOption[C]のcacheがSomeかNoneかを表す。
afの評価にかかった時間を記録し、bfの評価に割り当てられた時間からその時間を引くという操作が、val br = b.get(timeoutMs - at, TimeUnit.MILLISECONDS)の部分か?
def map2[A,B,C](a: Par[A], b: Par[B])(f: (A,B) => C): Par[C] =
es => {
val (af, bf) = (a(es), b(es))
Map2Future(af, bf, f)
}
case class Map2Future[A,B,C](a: Future[A], b: Future[B],
f: (A,B) => C) extends Future[C] {
@volatile var cache: Option[C] = None
def isDone = cache.isDefined
def isCancelled = a.isCancelled || b.isCancelled
def cancel(evenIfRunning: Boolean) =
a.cancel(evenIfRunning) || b.cancel(evenIfRunning)
def get = compute(Long.MaxValue)
def get(timeout: Long, units: TimeUnit): C =
compute(TimeUnit.MILLISECONDS.convert(timeout, units))
private def compute(timeoutMs: Long): C = cache match {
case Some(c) => c
case None =>
val start = System.currentTimeMillis
val ar = a.get(timeoutMs, TimeUnit.MILLISECONDS)
val stop = System.currentTimeMillis; val at = stop-start
val br = b.get(timeoutMs - at, TimeUnit.MILLISECONDS)
val ret = f(ar, br)
cache = Some(ret)
ret
}
}
Exercise7.4 lazyUnitを使って関数を記述せよ。この関数は任意の関数A=>Bから、その結果を非同期で評価する関数へと変換する。
def asyncF[A,B](f:A=>B):A=>Par[B]=
a => lazyUnit(f(a))
0 件のコメント:
コメントを投稿