# HG changeset patch # User wenzelm # Date 1586168924 -7200 # Node ID 0098b1974393df92f9daacbfa097660b73b0b4ed # Parent ca926ef898eb4aa082b71db62aed033fcd66d7b5 misc tuning and clarification; diff -r ca926ef898eb -r 0098b1974393 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() } }