support for uninterruptible execution;
authorwenzelm
Sat, 04 Apr 2020 13:45:21 +0200
changeset 71681 3622eea18e39
parent 71680 e20e117c3735
child 71682 c467a682f700
support for uninterruptible execution;
src/Pure/Concurrent/standard_thread.scala
--- a/src/Pure/Concurrent/standard_thread.scala	Fri Apr 03 20:49:49 2020 +0200
+++ b/src/Pure/Concurrent/standard_thread.scala	Sat Apr 04 13:45:21 2020 +0200
@@ -7,24 +7,26 @@
 package isabelle
 
 
-import java.lang.Thread
 import java.util.concurrent.{ThreadPoolExecutor, TimeUnit, LinkedBlockingQueue, ThreadFactory}
 
 
 object Standard_Thread
 {
-  /* fork */
-
-  def fork(name: String = "", daemon: Boolean = false)(body: => Unit): Thread =
+  def fork(name: String = "", daemon: Boolean = false)(body: => Unit): Standard_Thread =
   {
-    val thread =
-      if (name == null || name == "") new Thread() { override def run = body }
-      else new Thread(name) { override def run = body }
-    thread.setDaemon(daemon)
+    val thread = new Standard_Thread(name, daemon, body)
     thread.start
     thread
   }
 
+  def uninterruptible[A](body: => A): A =
+  {
+    Thread.currentThread match {
+      case thread: Standard_Thread => thread.uninterruptible(body)
+      case thread => error("uninterruptible: not a standard managed thread: " + thread)
+    }
+  }
+
 
   /* pool */
 
@@ -106,3 +108,38 @@
   def delay_last(delay: => Time, log: Logger = No_Logger)(event: => Unit): Delay =
     new Delay(false, delay, log, event)
 }
+
+class Standard_Thread private(name: String, daemon: Boolean, main: => Unit)
+  extends Thread()
+{
+  thread =>
+
+  proper_string(name).foreach(thread.setName)
+  thread.setDaemon(daemon)
+
+  override def run { main }
+
+  private var interruptible: Boolean = true
+  private var interrupt_pending: Boolean = false
+
+  override def interrupt: Unit = synchronized
+  {
+    if (interruptible) super.interrupt()
+    else { interrupt_pending = true }
+  }
+
+  private def uninterruptible[A](body: => A): A =
+  {
+    val interruptible0 = synchronized { val b = interruptible; interruptible = false; b }
+    try { body }
+    finally {
+      synchronized {
+        interruptible = interruptible0
+        if (interruptible && interrupt_pending) {
+          interrupt_pending = false
+          super.interrupt()
+        }
+      }
+    }
+  }
+}