| author | haftmann | 
| Tue, 10 Aug 2010 14:53:41 +0200 | |
| changeset 38312 | 9dd57db3c0f2 | 
| parent 34262 | a6d2d9c07e46 | 
| child 38848 | 9483bb678d96 | 
| 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 | |
| 31 | def join: A | |
| 32 |   def map[B](f: A => B): Future[B] = Future.fork { f(join) }
 | |
| 33 | ||
| 34 | override def toString = | |
| 35 |     peek match {
 | |
| 36 | case None => "<future>" | |
| 37 | case Some(Exn.Exn(_)) => "<failed>" | |
| 38 | case Some(Exn.Res(x)) => x.toString | |
| 39 | } | |
| 40 | } | |
| 41 | ||
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 42 | 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 | 43 | {
 | 
| 34262 | 44 | def fulfill_result(res: Exn.Result[A]): Unit | 
| 45 |   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 | 46 | } | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 47 | |
| 34217 | 48 | private class Finished_Future[A](x: A) extends Future[A] | 
| 49 | {
 | |
| 50 | val peek: Option[Exn.Result[A]] = Some(Exn.Res(x)) | |
| 51 | val join: A = x | |
| 52 | } | |
| 53 | ||
| 54 | private class Pending_Future[A](body: => A) extends Future[A] | |
| 55 | {
 | |
| 56 | @volatile private var result: Option[Exn.Result[A]] = None | |
| 57 | ||
| 58 |   private val evaluator = actor {
 | |
| 59 | result = Some(Exn.capture(body)) | |
| 60 |     loop { react { case _ => reply(result.get) } }
 | |
| 61 | } | |
| 62 | ||
| 63 | def peek: Option[Exn.Result[A]] = result | |
| 64 | ||
| 65 | def join: A = | |
| 66 |     Exn.release {
 | |
| 67 |       peek match {
 | |
| 68 | case Some(res) => res | |
| 69 | case None => (evaluator !? ()).asInstanceOf[Exn.Result[A]] | |
| 70 | } | |
| 71 | } | |
| 72 | } | |
| 73 | ||
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 74 | 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 | 75 | {
 | 
| 34262 | 76 | @volatile private var result: Option[Exn.Result[A]] = None | 
| 34217 | 77 | |
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 78 | private case object Read | 
| 34262 | 79 | 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 | 80 | |
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 81 |   private val receiver = actor {
 | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 82 |     loop {
 | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 83 |       react {
 | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 84 | case Read if result.isDefined => reply(result.get) | 
| 34262 | 85 | case Write(res) => | 
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 86 | if (result.isDefined) reply(false) | 
| 34262 | 87 |           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 | 88 | } | 
| 
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 | |
| 34262 | 92 | 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 | 93 | |
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 94 | def join: A = | 
| 34262 | 95 |     Exn.release {
 | 
| 96 |       result match {
 | |
| 97 | case Some(res) => res | |
| 98 | case None => (receiver !? Read).asInstanceOf[Exn.Result[A]] | |
| 99 | } | |
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 100 | } | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 101 | |
| 34262 | 102 |   def fulfill_result(res: Exn.Result[A]) {
 | 
| 103 |     receiver !? Write(res) match {
 | |
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 104 |       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 | 105 | case _ => | 
| 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 106 | } | 
| 
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 |