summaryrefslogtreecommitdiff
path: root/src/actors/scala/actors/Future.scala
diff options
context:
space:
mode:
authorPhilipp Haller <hallerp@gmail.com>2010-05-09 18:09:17 +0000
committerPhilipp Haller <hallerp@gmail.com>2010-05-09 18:09:17 +0000
commit8fe7b531649dd5f82b6ac46720c751750e893500 (patch)
tree6386d1c0b8a2d07c3f1a6467ede4667cff2b261b /src/actors/scala/actors/Future.scala
parentd1185713fa066528eac5f228aae943dd5ad3a142 (diff)
downloadscala-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.scala117
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
- }
- }
-
}