| author | wenzelm | 
| Wed, 17 May 2017 23:05:30 +0200 | |
| changeset 65860 | ce6be2e40d47 | 
| parent 64370 | 865b39487b5d | 
| child 71685 | d5773922358d | 
| permissions | -rw-r--r-- | 
| 34217 | 1 | /* Title: Pure/Concurrent/future.scala | 
| 2 | Author: Makarius | |
| 3 | ||
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 4 | Value-oriented parallel execution via futures and promises. | 
| 34217 | 5 | */ | 
| 6 | ||
| 7 | package isabelle | |
| 8 | ||
| 9 | ||
| 61563 | 10 | import java.util.concurrent.Callable | 
| 11 | ||
| 12 | ||
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 13 | /* futures and promises */ | 
| 34217 | 14 | |
| 15 | object Future | |
| 16 | {
 | |
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 17 | def value[A](x: A): Future[A] = new Value_Future(x) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 18 | def fork[A](body: => A): Future[A] = new Task_Future[A](body) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 19 | def promise[A]: Promise[A] = new Promise_Future[A] | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 20 | def thread[A](name: String = "", daemon: Boolean = false)(body: => A): Future[A] = | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 21 | new Thread_Future[A](name, daemon, body) | 
| 34217 | 22 | } | 
| 23 | ||
| 56673 
42bf8fffdf6a
modernized Future/Promise implementation, bypassing old actors;
 wenzelm parents: 
56663diff
changeset | 24 | trait Future[A] | 
| 34217 | 25 | {
 | 
| 26 | def peek: Option[Exn.Result[A]] | |
| 27 | 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 | 28 |   def get_finished: A = { require(is_finished); Exn.release(peek.get) }
 | 
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 29 | def join_result: Exn.Result[A] | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 30 | def join: A = Exn.release(join_result) | 
| 34217 | 31 |   def map[B](f: A => B): Future[B] = Future.fork { f(join) }
 | 
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 32 | def cancel: Unit | 
| 34217 | 33 | |
| 57912 | 34 | override def toString: String = | 
| 34217 | 35 |     peek match {
 | 
| 36 | case None => "<future>" | |
| 37 | case Some(Exn.Exn(_)) => "<failed>" | |
| 38 | case Some(Exn.Res(x)) => x.toString | |
| 39 | } | |
| 40 | } | |
| 41 | ||
| 56673 
42bf8fffdf6a
modernized Future/Promise implementation, bypassing old actors;
 wenzelm parents: 
56663diff
changeset | 42 | trait Promise[A] extends Future[A] | 
| 34240 
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 | 
| 56674 | 45 | def fulfill(x: A): Unit | 
| 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 | |
| 56673 
42bf8fffdf6a
modernized Future/Promise implementation, bypassing old actors;
 wenzelm parents: 
56663diff
changeset | 48 | |
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 49 | /* value future */ | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 50 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 51 | private class Value_Future[A](x: A) extends Future[A] | 
| 34217 | 52 | {
 | 
| 53 | val peek: Option[Exn.Result[A]] = Some(Exn.Res(x)) | |
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 54 | def join_result: Exn.Result[A] = peek.get | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 55 |   def cancel {}
 | 
| 34217 | 56 | } | 
| 57 | ||
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 58 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 59 | /* task future via thread pool */ | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 60 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 61 | private class Task_Future[A](body: => A) extends Future[A] | 
| 34217 | 62 | {
 | 
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 63 | private sealed abstract class Status | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 64 | private case object Ready extends Status | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 65 | private case class Running(thread: Thread) extends Status | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 66 | private case object Terminated extends Status | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 67 | private case class Finished(result: Exn.Result[A]) extends Status | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 68 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 69 | private val status = Synchronized[Status](Ready) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 70 | |
| 56673 
42bf8fffdf6a
modernized Future/Promise implementation, bypassing old actors;
 wenzelm parents: 
56663diff
changeset | 71 | def peek: Option[Exn.Result[A]] = | 
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 72 |     status.value match {
 | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 73 | case Finished(result) => Some(result) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 74 | case _ => None | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 75 | } | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 76 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 77 | private def try_run() | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 78 |   {
 | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 79 | val do_run = | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 80 |       status.change_result {
 | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 81 | case Ready => (true, Running(Thread.currentThread)) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 82 | case st => (false, st) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 83 | } | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 84 |     if (do_run) {
 | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 85 | val result = Exn.capture(body) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 86 | status.change(_ => Terminated) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 87 | status.change(_ => Finished(if (Thread.interrupted) Exn.Exn(Exn.Interrupt()) else result)) | 
| 56673 
42bf8fffdf6a
modernized Future/Promise implementation, bypassing old actors;
 wenzelm parents: 
56663diff
changeset | 88 | } | 
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 89 | } | 
| 62247 
ec35b8aca636
proper try_run for exactly one evaluation of body (amending 91c3aedbfc5e);
 wenzelm parents: 
61563diff
changeset | 90 |   private val task = Standard_Thread.pool.submit(new Callable[Unit] { def call = try_run() })
 | 
| 34217 | 91 | |
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 92 | def join_result: Exn.Result[A] = | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 93 |   {
 | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 94 | try_run() | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 95 |     status.guarded_access {
 | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 96 | case st @ Finished(result) => Some((result, st)) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 97 | case _ => None | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 98 | } | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 99 | } | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 100 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 101 | def cancel = | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 102 |   {
 | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 103 |     status.change {
 | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 104 | case Ready => task.cancel(false); Finished(Exn.Exn(Exn.Interrupt())) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 105 | case st @ Running(thread) => thread.interrupt; st | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 106 | case st => st | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 107 | } | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 108 | } | 
| 34217 | 109 | } | 
| 110 | ||
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 111 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 112 | /* promise future */ | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 113 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 114 | private class Promise_Future[A] extends Promise[A] | 
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 115 | {
 | 
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 116 | private val state = Synchronized[Option[Exn.Result[A]]](None) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 117 | def peek: Option[Exn.Result[A]] = state.value | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 118 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 119 | def join_result: Exn.Result[A] = | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 120 | state.guarded_access(st => if (st.isEmpty) None else Some((st.get, st))) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 121 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 122 | def fulfill_result(result: Exn.Result[A]): Unit = | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 123 | state.change(st => if (st.isEmpty) Some(result) else throw new IllegalStateException) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 124 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 125 | def fulfill(x: A): Unit = 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 | 126 | |
| 59365 | 127 | def cancel: Unit = | 
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 128 | state.change(st => if (st.isEmpty) Some(Exn.Exn(Exn.Interrupt())) else st) | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 129 | } | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 130 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 131 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 132 | /* thread future */ | 
| 59365 | 133 | |
| 61559 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 134 | private class Thread_Future[A](name: String, daemon: Boolean, body: => A) extends Future[A] | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 135 | {
 | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 136 | private val result = Future.promise[A] | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 137 | private val thread = | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 138 |     Standard_Thread.fork(name, daemon) { result.fulfill_result(Exn.capture(body)) }
 | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 139 | |
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 140 | def peek: Option[Exn.Result[A]] = result.peek | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 141 | def join_result: Exn.Result[A] = result.join_result | 
| 
313eca3fa847
more direct task future implementation, with proper cancel operation;
 wenzelm parents: 
61556diff
changeset | 142 | def cancel: Unit = thread.interrupt | 
| 34240 
3274571e45c1
added Future.promise -- essentially a single-assignment variable with signalling, using the Future interface;
 wenzelm parents: 
34217diff
changeset | 143 | } |