src/Pure/Concurrent/isabelle_thread.scala
changeset 71702 0098b1974393
parent 71701 ca926ef898eb
child 71703 8ec5c82b67dc
equal deleted inserted replaced
71701:ca926ef898eb 71702:0098b1974393
    38     thread.start
    38     thread.start
    39     thread
    39     thread
    40   }
    40   }
    41 
    41 
    42 
    42 
    43   /* self */
    43   /* self-thread */
    44 
    44 
    45   def self: Isabelle_Thread =
    45   def self: Isabelle_Thread =
    46     Thread.currentThread match {
    46     Thread.currentThread match {
    47       case thread: Isabelle_Thread => thread
    47       case thread: Isabelle_Thread => thread
    48       case _ => error("Isabelle-specific thread required")
    48       case _ => error("Isabelle-specific thread required")
    49     }
    49     }
    50 
    50 
    51 
    51 
    52   /* interrupts */
    52   /* interrupt handlers */
    53 
    53 
    54   type Interrupt_Handler = Isabelle_Thread => Unit
    54   object Interrupt_Handler
       
    55   {
       
    56     def apply(handle: Isabelle_Thread => Unit, name: String = "handler"): Interrupt_Handler =
       
    57       new Interrupt_Handler(handle, name)
       
    58 
       
    59     val interruptible: Interrupt_Handler =
       
    60       Interrupt_Handler(_.raise_interrupt, name = "interruptible")
       
    61 
       
    62     val uninterruptible: Interrupt_Handler =
       
    63       Interrupt_Handler(_.postpone_interrupt, name = "uninterruptible")
       
    64   }
       
    65 
       
    66   class Interrupt_Handler private(handle: Isabelle_Thread => Unit, name: String)
       
    67     extends Function[Isabelle_Thread, Unit]
       
    68   {
       
    69     def apply(thread: Isabelle_Thread) { handle(thread) }
       
    70     override def toString: String = name
       
    71   }
    55 
    72 
    56   def interrupt_handler[A](handler: Interrupt_Handler)(body: => A): A =
    73   def interrupt_handler[A](handler: Interrupt_Handler)(body: => A): A =
    57     self.interrupt_handler(handler)(body)
    74     self.interrupt_handler(handler)(body)
    58 
    75 
    59   def interruptible[A](body: => A): A = interrupt_handler(_.raise_interrupt)(body)
    76   def interrupt_handler[A](handle: Isabelle_Thread => Unit)(body: => A): A =
    60   def uninterruptible[A](body: => A): A = interrupt_handler(_.postpone_interrupt)(body)
    77     self.interrupt_handler(Interrupt_Handler(handle))(body)
    61 
    78 
    62 
    79   def interruptible[A](body: => A): A =
    63   /* pool */
    80     interrupt_handler(Interrupt_Handler.interruptible)(body)
       
    81 
       
    82   def uninterruptible[A](body: => A): A =
       
    83     interrupt_handler(Interrupt_Handler.uninterruptible)(body)
       
    84 
       
    85 
       
    86   /* thread pool */
    64 
    87 
    65   lazy val pool: ThreadPoolExecutor =
    88   lazy val pool: ThreadPoolExecutor =
    66     {
    89     {
    67       val m = Value.Int.unapply(System.getProperty("isabelle.threads", "0")) getOrElse 0
    90       val m = Value.Int.unapply(System.getProperty("isabelle.threads", "0")) getOrElse 0
    68       val n = if (m > 0) m else (Runtime.getRuntime.availableProcessors max 1) min 8
    91       val n = if (m > 0) m else (Runtime.getRuntime.availableProcessors max 1) min 8
   147   thread.setPriority(pri)
   170   thread.setPriority(pri)
   148   thread.setDaemon(daemon)
   171   thread.setDaemon(daemon)
   149 
   172 
   150   override def run { main.run() }
   173   override def run { main.run() }
   151 
   174 
       
   175   def is_self: Boolean = Thread.currentThread == thread
       
   176 
   152 
   177 
   153   /* interrupt state */
   178   /* interrupt state */
   154 
   179 
   155   private var interrupt_pending: Boolean = false
   180   // synchronized, with concurrent changes
       
   181   private var interrupt_postponed: Boolean = false
       
   182 
       
   183   def clear_interrupt: Boolean = synchronized
       
   184   {
       
   185     val was_interrupted = isInterrupted || interrupt_postponed
       
   186     Exn.Interrupt.dispose()
       
   187     interrupt_postponed = false
       
   188     was_interrupted
       
   189   }
   156 
   190 
   157   def raise_interrupt: Unit = synchronized
   191   def raise_interrupt: Unit = synchronized
   158   {
   192   {
   159     interrupt_pending = false
   193     interrupt_postponed = false
   160     super.interrupt()
   194     super.interrupt()
   161   }
   195   }
   162 
   196 
   163   def postpone_interrupt: Unit = synchronized
   197   def postpone_interrupt: Unit = synchronized
   164   {
   198   {
   165     interrupt_pending = true
   199     interrupt_postponed = true
   166     Exn.Interrupt.dispose()
   200     Exn.Interrupt.dispose()
   167   }
   201   }
   168 
   202 
   169 
   203 
   170   /* interrupt handler */
   204   /* interrupt handler */
   171 
   205 
   172   private var handler: Isabelle_Thread.Interrupt_Handler = (_.raise_interrupt)
   206   // non-synchronized, only changed on self-thread
   173 
   207   @volatile private var handler = Isabelle_Thread.Interrupt_Handler.interruptible
   174   override def interrupt: Unit = (synchronized { handler })(thread)
   208 
       
   209   override def interrupt: Unit = handler(thread)
   175 
   210 
   176   def interrupt_handler[A](new_handler: Isabelle_Thread.Interrupt_Handler)(body: => A): A =
   211   def interrupt_handler[A](new_handler: Isabelle_Thread.Interrupt_Handler)(body: => A): A =
   177   {
   212   {
   178     require(Thread.currentThread == thread)
   213     require(is_self)
   179 
   214 
   180     val old_handler = handler
   215     val old_handler = handler
   181     handler = new_handler
   216     handler = new_handler
   182     try { body }
   217     try {
       
   218       if (clear_interrupt) interrupt
       
   219       body
       
   220     }
   183     finally {
   221     finally {
   184       synchronized {
   222       handler = old_handler
   185         handler = old_handler
   223       if (clear_interrupt) interrupt
   186         if (isInterrupted || interrupt_pending) thread.interrupt
       
   187       }
       
   188       Exn.Interrupt.expose()
   224       Exn.Interrupt.expose()
   189     }
   225     }
   190   }
   226   }
   191 }
   227 }