| author | blanchet | 
| Mon, 06 Jun 2011 20:36:35 +0200 | |
| changeset 43181 | cd3b7798ecc2 | 
| parent 38848 | 9483bb678d96 | 
| child 45667 | 546d78f0d81f | 
| permissions | -rw-r--r-- | 
| 34217 | 1 | /* Title: Pure/Concurrent/future.scala | 
| 2 | Author: Makarius | |
| 3 | ||
| 4 | Future values. | |
| 5 | ||
| 6 | Notable differences to scala.actors.Future (as of Scala 2.7.7): | |
| 7 | ||
| 8 | * We capture/release exceptions as in the ML variant. | |
| 9 | ||
| 10 | * Future.join works for *any* actor, not just the one of the | |
| 11 | original fork. | |
| 12 | */ | |
| 13 | ||
| 14 | package isabelle | |
| 15 | ||
| 16 | ||
| 17 | import scala.actors.Actor._ | |
| 18 | ||
| 19 | ||
| 20 | object Future | |
| 21 | {
 | |
| 22 | def value[A](x: A): Future[A] = new Finished_Future(x) | |
| 23 | def fork[A](body: => A): Future[A] = new Pending_Future(body) | |
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 24 | def promise[A]: Promise[A] = new Promise_Future | 
| 34217 | 25 | } | 
| 26 | ||
| 27 | abstract class Future[A] | |
| 28 | {
 | |
| 29 | def peek: Option[Exn.Result[A]] | |
| 30 | def is_finished: Boolean = peek.isDefined | |
| 38848 
9483bb678d96
use Future.get_finished where this is the intended meaning -- prefer immediate crash over deadlock due to promises that are never fulfilled;
 wenzelm parents: 
34262diff
changeset | 31 |   def get_finished: A = { require(is_finished); Exn.release(peek.get) }
 | 
| 34217 | 32 | def join: A | 
| 33 |   def map[B](f: A => B): Future[B] = Future.fork { f(join) }
 | |
| 34 | ||
| 35 | override def toString = | |
| 36 |     peek match {
 | |
| 37 | case None => "<future>" | |
| 38 | case Some(Exn.Exn(_)) => "<failed>" | |
| 39 | case Some(Exn.Res(x)) => x.toString | |
| 40 | } | |
| 41 | } | |
| 42 | ||
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 43 | abstract class Promise[A] extends Future[A] | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 44 | {
 | 
| 34262 | 45 | def fulfill_result(res: Exn.Result[A]): Unit | 
| 46 |   def fulfill(x: A) { fulfill_result(Exn.Res(x)) }
 | |
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 47 | } | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 48 | |
| 34217 | 49 | private class Finished_Future[A](x: A) extends Future[A] | 
| 50 | {
 | |
| 51 | val peek: Option[Exn.Result[A]] = Some(Exn.Res(x)) | |
| 52 | val join: A = x | |
| 53 | } | |
| 54 | ||
| 55 | private class Pending_Future[A](body: => A) extends Future[A] | |
| 56 | {
 | |
| 57 | @volatile private var result: Option[Exn.Result[A]] = None | |
| 58 | ||
| 59 |   private val evaluator = actor {
 | |
| 60 | result = Some(Exn.capture(body)) | |
| 61 |     loop { react { case _ => reply(result.get) } }
 | |
| 62 | } | |
| 63 | ||
| 64 | def peek: Option[Exn.Result[A]] = result | |
| 65 | ||
| 66 | def join: A = | |
| 67 |     Exn.release {
 | |
| 68 |       peek match {
 | |
| 69 | case Some(res) => res | |
| 70 | case None => (evaluator !? ()).asInstanceOf[Exn.Result[A]] | |
| 71 | } | |
| 72 | } | |
| 73 | } | |
| 74 | ||
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 75 | private class Promise_Future[A] extends Promise[A] | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 76 | {
 | 
| 34262 | 77 | @volatile private var result: Option[Exn.Result[A]] = None | 
| 34217 | 78 | |
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 79 | private case object Read | 
| 34262 | 80 | private case class Write(res: Exn.Result[A]) | 
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 81 | |
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 82 |   private val receiver = actor {
 | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 83 |     loop {
 | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 84 |       react {
 | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 85 | case Read if result.isDefined => reply(result.get) | 
| 34262 | 86 | case Write(res) => | 
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 87 | if (result.isDefined) reply(false) | 
| 34262 | 88 |           else { result = Some(res); reply(true) }
 | 
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 89 | } | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 90 | } | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 91 | } | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 92 | |
| 34262 | 93 | def peek: Option[Exn.Result[A]] = result | 
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 94 | |
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 95 | def join: A = | 
| 34262 | 96 |     Exn.release {
 | 
| 97 |       result match {
 | |
| 98 | case Some(res) => res | |
| 99 | case None => (receiver !? Read).asInstanceOf[Exn.Result[A]] | |
| 100 | } | |
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 101 | } | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 102 | |
| 34262 | 103 |   def fulfill_result(res: Exn.Result[A]) {
 | 
| 104 |     receiver !? Write(res) match {
 | |
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 105 |       case false => error("Duplicate fulfillment of promise")
 | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 106 | case _ => | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 107 | } | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 108 | } | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 109 | } | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 110 |