misc tuning and clarification;
authorwenzelm
Mon, 06 Apr 2020 12:28:44 +0200
changeset 71702 0098b1974393
parent 71701 ca926ef898eb
child 71703 8ec5c82b67dc
misc tuning and clarification;
src/Pure/Concurrent/isabelle_thread.scala
--- a/src/Pure/Concurrent/isabelle_thread.scala	Sun Apr 05 22:08:52 2020 +0200
+++ b/src/Pure/Concurrent/isabelle_thread.scala	Mon Apr 06 12:28:44 2020 +0200
@@ -40,7 +40,7 @@
   }
 
 
-  /* self */
+  /* self-thread */
 
   def self: Isabelle_Thread =
     Thread.currentThread match {
@@ -49,18 +49,41 @@
     }
 
 
-  /* interrupts */
+  /* interrupt handlers */
+
+  object Interrupt_Handler
+  {
+    def apply(handle: Isabelle_Thread => Unit, name: String = "handler"): Interrupt_Handler =
+      new Interrupt_Handler(handle, name)
+
+    val interruptible: Interrupt_Handler =
+      Interrupt_Handler(_.raise_interrupt, name = "interruptible")
 
-  type Interrupt_Handler = Isabelle_Thread => Unit
+    val uninterruptible: Interrupt_Handler =
+      Interrupt_Handler(_.postpone_interrupt, name = "uninterruptible")
+  }
+
+  class Interrupt_Handler private(handle: Isabelle_Thread => Unit, name: String)
+    extends Function[Isabelle_Thread, Unit]
+  {
+    def apply(thread: Isabelle_Thread) { handle(thread) }
+    override def toString: String = name
+  }
 
   def interrupt_handler[A](handler: Interrupt_Handler)(body: => A): A =
     self.interrupt_handler(handler)(body)
 
-  def interruptible[A](body: => A): A = interrupt_handler(_.raise_interrupt)(body)
-  def uninterruptible[A](body: => A): A = interrupt_handler(_.postpone_interrupt)(body)
+  def interrupt_handler[A](handle: Isabelle_Thread => Unit)(body: => A): A =
+    self.interrupt_handler(Interrupt_Handler(handle))(body)
+
+  def interruptible[A](body: => A): A =
+    interrupt_handler(Interrupt_Handler.interruptible)(body)
+
+  def uninterruptible[A](body: => A): A =
+    interrupt_handler(Interrupt_Handler.uninterruptible)(body)
 
 
-  /* pool */
+  /* thread pool */
 
   lazy val pool: ThreadPoolExecutor =
     {
@@ -149,42 +172,55 @@
 
   override def run { main.run() }
 
+  def is_self: Boolean = Thread.currentThread == thread
+
 
   /* interrupt state */
 
-  private var interrupt_pending: Boolean = false
+  // synchronized, with concurrent changes
+  private var interrupt_postponed: Boolean = false
+
+  def clear_interrupt: Boolean = synchronized
+  {
+    val was_interrupted = isInterrupted || interrupt_postponed
+    Exn.Interrupt.dispose()
+    interrupt_postponed = false
+    was_interrupted
+  }
 
   def raise_interrupt: Unit = synchronized
   {
-    interrupt_pending = false
+    interrupt_postponed = false
     super.interrupt()
   }
 
   def postpone_interrupt: Unit = synchronized
   {
-    interrupt_pending = true
+    interrupt_postponed = true
     Exn.Interrupt.dispose()
   }
 
 
   /* interrupt handler */
 
-  private var handler: Isabelle_Thread.Interrupt_Handler = (_.raise_interrupt)
+  // non-synchronized, only changed on self-thread
+  @volatile private var handler = Isabelle_Thread.Interrupt_Handler.interruptible
 
-  override def interrupt: Unit = (synchronized { handler })(thread)
+  override def interrupt: Unit = handler(thread)
 
   def interrupt_handler[A](new_handler: Isabelle_Thread.Interrupt_Handler)(body: => A): A =
   {
-    require(Thread.currentThread == thread)
+    require(is_self)
 
     val old_handler = handler
     handler = new_handler
-    try { body }
+    try {
+      if (clear_interrupt) interrupt
+      body
+    }
     finally {
-      synchronized {
-        handler = old_handler
-        if (isInterrupted || interrupt_pending) thread.interrupt
-      }
+      handler = old_handler
+      if (clear_interrupt) interrupt
       Exn.Interrupt.expose()
     }
   }