diff options
author | Philipp Haller <hallerp@gmail.com> | 2010-05-09 18:09:17 +0000 |
---|---|---|
committer | Philipp Haller <hallerp@gmail.com> | 2010-05-09 18:09:17 +0000 |
commit | 8fe7b531649dd5f82b6ac46720c751750e893500 (patch) | |
tree | 6386d1c0b8a2d07c3f1a6467ede4667cff2b261b /src/actors/scala/actors/Future.scala | |
parent | d1185713fa066528eac5f228aae943dd5ad3a142 (diff) | |
download | scala-8fe7b531649dd5f82b6ac46720c751750e893500.tar.gz scala-8fe7b531649dd5f82b6ac46720c751750e893500.tar.bz2 scala-8fe7b531649dd5f82b6ac46720c751750e893500.zip |
Closes #3407. Closes #3412. Review by plocinic.
Diffstat (limited to 'src/actors/scala/actors/Future.scala')
-rw-r--r-- | src/actors/scala/actors/Future.scala | 117 |
1 files changed, 60 insertions, 57 deletions
diff --git a/src/actors/scala/actors/Future.scala b/src/actors/scala/actors/Future.scala index 9f65786879..e34569f36b 100644 --- a/src/actors/scala/actors/Future.scala +++ b/src/actors/scala/actors/Future.scala @@ -11,6 +11,7 @@ package scala.actors import scala.actors.scheduler.DaemonScheduler +import scala.concurrent.SyncVar /** A `Future[T]` is a function of arity 0 that returns * a value of type `T`. @@ -22,7 +23,8 @@ import scala.actors.scheduler.DaemonScheduler * * @author Philipp Haller */ -abstract class Future[+T](val inputChannel: InputChannel[T]) extends Responder[T] with Function0[T] { +abstract class Future[+T] extends Responder[T] with Function0[T] { + @volatile private[actors] var fvalue: Option[Any] = None private[actors] def fvalueTyped = fvalue.get.asInstanceOf[T] @@ -41,57 +43,79 @@ abstract class Future[+T](val inputChannel: InputChannel[T]) extends Responder[T * `false` otherwise. */ def isSet: Boolean -} -/** The `Futures` object contains methods that operate on futures. - * - * @author Philipp Haller - */ -object Futures { + /** Returns an input channel that can be used to receive the future's result. + * + * @return the future's input channel + */ + def inputChannel: InputChannel[T] - import scala.concurrent.SyncVar +} - private case object Eval +private case object Eval - private class FutureActor[T](fun: SyncVar[T] => Unit, channel: Channel[T]) - extends Future[T](channel) with DaemonActor { +private class FutureActor[T](fun: SyncVar[T] => Unit, channel: Channel[T]) extends Future[T] with DaemonActor { - import Actor._ + var enableChannel = false // guarded by this - def isSet = !fvalue.isEmpty + def isSet = !fvalue.isEmpty - def apply(): T = { - if (fvalue.isEmpty) - this !? Eval - fvalueTyped + def apply(): T = { + if (fvalue.isEmpty) { + this !? Eval } + fvalueTyped + } - def respond(k: T => Unit) { - if (isSet) k(fvalueTyped) - else { - val ft = this !! Eval - ft.inputChannel.react { - case _ => k(fvalueTyped) - } + def respond(k: T => Unit) { + if (isSet) k(fvalueTyped) + else { + val ft = this !! Eval + ft.inputChannel.react { + case _ => k(fvalueTyped) } } + } - def act() { - val res = new SyncVar[T] - - { - fun(res) - } andThen { - fvalue = Some(res.get) - channel ! res.get - loop { - react { - case Eval => reply() - } + def inputChannel: InputChannel[T] = { + synchronized { + if (!enableChannel) { + if (isSet) + channel ! fvalueTyped + enableChannel = true + } + } + channel + } + + def act() { + val res = new SyncVar[T] + + { + fun(res) + } andThen { + + synchronized { + val v = res.get + fvalue = Some(v) + if (enableChannel) + channel ! v + } + + loop { + react { + case Eval => reply() } } } } +} + +/** The `Futures` object contains methods that operate on futures. + * + * @author Philipp Haller + */ +object Futures { /** Arranges for the asynchronous execution of `body`, * returning a future representing the result. @@ -222,25 +246,4 @@ object Futures { results } - private[actors] def fromInputChannel[T](inputChannel: InputChannel[T]): Future[T] = - new Future[T](inputChannel) { - def apply() = - if (isSet) fvalueTyped - else inputChannel.receive { - case any => fvalue = Some(any); fvalueTyped - } - def respond(k: T => Unit): Unit = - if (isSet) k(fvalueTyped) - else inputChannel.react { - case any => fvalue = Some(any); k(fvalueTyped) - } - def isSet = fvalue match { - case None => inputChannel.receiveWithin(0) { - case TIMEOUT => false - case any => fvalue = Some(any); true - } - case Some(_) => true - } - } - } |