src/Pure/Concurrent/par_list.scala
author wenzelm
Thu, 11 Dec 2014 23:31:30 +0100
changeset 59136 c2b23cb8a677
child 59137 fd748d770770
permissions -rw-r--r--
added Par_List in Scala, in accordance to ML version; system property "isabelle.threads" determines size of Scala thread pool, like system option "threads" for ML; avoid ".par" framework with its hard-wired thread pool, which also has problems with cancellation; tuned;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
59136
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/Concurrent/par_list.scala
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
     3
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
     4
Parallel list combinators.
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
     5
*/
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
     6
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
     7
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
     8
package isabelle
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
     9
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    10
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    11
import java.util.concurrent.{Future => JFuture, CancellationException}
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    12
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    13
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    14
object Par_List
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    15
{
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    16
  def managed_results[A, B](f: A => B, xs: List[A]): List[Exn.Result[B]] =
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    17
    if (xs.isEmpty || xs.tail.isEmpty) xs.map(x => Exn.capture { f(x) })
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    18
    else {
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    19
      val state = Synchronized((List.empty[JFuture[Exn.Result[B]]], false))
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    20
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    21
      def cancel_other(self: Int = -1): Unit =
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    22
        state.change { case (tasks, canceled) =>
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    23
          if (!canceled) {
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    24
            for ((task, i) <- tasks.iterator.zipWithIndex if i != self)
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    25
              task.cancel(true)
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    26
          }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    27
          (tasks, true)
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    28
        }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    29
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    30
      try {
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    31
        state.change(_ =>
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    32
          (xs.iterator.zipWithIndex.map({ case (x, self) =>
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    33
            Simple_Thread.submit_task {
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    34
              val result = Exn.capture { f(x) }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    35
              result match { case Exn.Exn(_) => cancel_other(self) case _ => }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    36
              result
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    37
            }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    38
          }).toList, false))
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    39
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    40
        state.value._1.map(future =>
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    41
          try { future.get }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    42
          catch { case _: CancellationException => Exn.Exn(Exn.Interrupt()): Exn.Result[B] })
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    43
      }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    44
      finally { cancel_other() }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    45
    }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    46
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    47
  def map[A, B](f: A => B, xs: List[A]): List[B] =
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    48
    Exn.release_first(managed_results(f, xs))
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    49
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    50
  def get_some[A, B](f: A => Option[B], xs: List[A]): Option[B] =
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    51
  {
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    52
    class Found(val res: B) extends Exception
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    53
    val results =
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    54
      managed_results(
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    55
        (x: A) => f(x) match { case None => () case Some(y) => throw new Found(y) }, xs)
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    56
    results.collectFirst({ case Exn.Exn(found: Found) => found.res }) match {
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    57
      case None => Exn.release_first(results); None
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    58
      case some => some
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    59
    }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    60
  }
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    61
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    62
  def find_some[A](P: A => Boolean, xs: List[A]): Option[A] =
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    63
    get_some((x: A) => if (P(x)) Some(x) else None, xs)
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    64
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    65
  def exists[A](P: A => Boolean, xs: List[A]): Boolean =
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    66
    get_some((x: A) => if (P(x)) Some(()) else None, xs).isDefined
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    67
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    68
  def forall[A](P: A => Boolean, xs: List[A]): Boolean = !exists((x: A) => !P(x), xs)
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    69
}
c2b23cb8a677 added Par_List in Scala, in accordance to ML version;
wenzelm
parents:
diff changeset
    70