| 71704 |      1 | /*  Title:      Pure/Concurrent/delay.scala
 | 
|  |      2 |     Author:     Makarius
 | 
|  |      3 | 
 | 
|  |      4 | Delayed events.
 | 
|  |      5 | */
 | 
|  |      6 | 
 | 
|  |      7 | package isabelle
 | 
|  |      8 | 
 | 
|  |      9 | 
 | 
| 75393 |     10 | object Delay {
 | 
| 71704 |     11 |   // delayed event after first invocation
 | 
|  |     12 |   def first(delay: => Time, log: Logger = No_Logger, gui: Boolean = false)(event: => Unit): Delay =
 | 
|  |     13 |     new Delay(true, delay, log, if (gui) GUI_Thread.later { event } else event )
 | 
|  |     14 | 
 | 
|  |     15 |   // delayed event after last invocation
 | 
|  |     16 |   def last(delay: => Time, log: Logger = No_Logger, gui: Boolean = false)(event: => Unit): Delay =
 | 
|  |     17 |     new Delay(false, delay, log, if (gui) GUI_Thread.later { event } else event )
 | 
|  |     18 | }
 | 
|  |     19 | 
 | 
| 75393 |     20 | final class Delay private(first: Boolean, delay: => Time, log: Logger, event: => Unit) {
 | 
| 71704 |     21 |   private var running: Option[Event_Timer.Request] = None
 | 
|  |     22 | 
 | 
| 75393 |     23 |   private def run: Unit = {
 | 
| 71704 |     24 |     val do_run = synchronized {
 | 
|  |     25 |       if (running.isDefined) { running = None; true } else false
 | 
|  |     26 |     }
 | 
|  |     27 |     if (do_run) {
 | 
|  |     28 |       try { event }
 | 
|  |     29 |       catch { case exn: Throwable if !Exn.is_interrupt(exn) => log(Exn.message(exn)); throw exn }
 | 
|  |     30 |     }
 | 
|  |     31 |   }
 | 
|  |     32 | 
 | 
| 77182 |     33 |   def invoke(msg: String = ""): Unit = synchronized {
 | 
|  |     34 |     if (msg.nonEmpty) log("Delay.invoke " + msg)
 | 
| 71704 |     35 |     val new_run =
 | 
|  |     36 |       running match {
 | 
| 73367 |     37 |         case Some(request) => if (first) false else { request.cancel(); true }
 | 
| 71704 |     38 |         case None => true
 | 
|  |     39 |       }
 | 
|  |     40 |     if (new_run)
 | 
|  |     41 |       running = Some(Event_Timer.request(Time.now() + delay)(run))
 | 
|  |     42 |   }
 | 
|  |     43 | 
 | 
| 77182 |     44 |   def revoke(msg: String = ""): Unit = synchronized {
 | 
|  |     45 |     if (msg.nonEmpty) log("Delay.revoke " + msg)
 | 
| 71704 |     46 |     running match {
 | 
| 73367 |     47 |       case Some(request) => request.cancel(); running = None
 | 
| 71704 |     48 |       case None =>
 | 
|  |     49 |     }
 | 
|  |     50 |   }
 | 
|  |     51 | 
 | 
| 77182 |     52 |   def postpone(alt_delay: Time, msg: String = ""): Unit = synchronized {
 | 
|  |     53 |     if (msg.nonEmpty) log("Delay.postpone " + msg)
 | 
| 71704 |     54 |     running match {
 | 
|  |     55 |       case Some(request) =>
 | 
|  |     56 |         val alt_time = Time.now() + alt_delay
 | 
| 73367 |     57 |         if (request.time < alt_time && request.cancel()) {
 | 
| 71704 |     58 |           running = Some(Event_Timer.request(alt_time)(run))
 | 
|  |     59 |         }
 | 
|  |     60 |       case None =>
 | 
|  |     61 |     }
 | 
|  |     62 |   }
 | 
|  |     63 | }
 |