src/Pure/System/session.scala
changeset 37129 4c83696b340e
parent 37065 2a73253b5898
child 37132 10ef4da1c314
equal deleted inserted replaced
37128:1b6a4d9f397a 37129:4c83696b340e
    23   type Entity_ID = String
    23   type Entity_ID = String
    24 
    24 
    25   trait Entity
    25   trait Entity
    26   {
    26   {
    27     val id: Entity_ID
    27     val id: Entity_ID
    28     def consume(session: Session, message: XML.Tree): Unit
    28     def consume(message: XML.Tree, forward: Command => Unit): Unit
    29   }
    29   }
    30 }
    30 }
    31 
    31 
    32 
    32 
    33 class Session(system: Isabelle_System)
    33 class Session(system: Isabelle_System)
    35   /* pervasive event buses */
    35   /* pervasive event buses */
    36 
    36 
    37   val global_settings = new Event_Bus[Session.Global_Settings.type]
    37   val global_settings = new Event_Bus[Session.Global_Settings.type]
    38   val raw_results = new Event_Bus[Isabelle_Process.Result]
    38   val raw_results = new Event_Bus[Isabelle_Process.Result]
    39   val raw_output = new Event_Bus[Isabelle_Process.Result]
    39   val raw_output = new Event_Bus[Isabelle_Process.Result]
    40   val results = new Event_Bus[Command]
    40   val commands_changed = new Event_Bus[Command_Set]
    41 
       
    42   val command_change = new Event_Bus[Command]
       
    43 
    41 
    44 
    42 
    45   /* unique ids */
    43   /* unique ids */
    46 
    44 
    47   private var id_count: BigInt = 0
    45   private var id_count: BigInt = 0
    64 
    62 
    65   private case class Start(timeout: Int, args: List[String])
    63   private case class Start(timeout: Int, args: List[String])
    66   private case object Stop
    64   private case object Stop
    67   private case class Begin_Document(path: String)
    65   private case class Begin_Document(path: String)
    68 
    66 
    69   private val session_actor = actor {
    67   private lazy val session_actor = actor {
    70 
    68 
    71     var prover: Isabelle_Process with Isar_Document = null
    69     var prover: Isabelle_Process with Isar_Document = null
    72 
    70 
    73     def register(entity: Session.Entity) { entities += (entity.id -> entity) }
    71     def register(entity: Session.Entity) { entities += (entity.id -> entity) }
    74 
    72 
   116       val target: Option[Session.Entity] =
   114       val target: Option[Session.Entity] =
   117         target_id match {
   115         target_id match {
   118           case None => None
   116           case None => None
   119           case Some(id) => lookup_entity(id)
   117           case Some(id) => lookup_entity(id)
   120         }
   118         }
   121       if (target.isDefined) target.get.consume(this, result.message)
   119       if (target.isDefined) target.get.consume(result.message, indicate_command_change)
   122       else if (result.kind == Isabelle_Process.Kind.STATUS) {
   120       else if (result.kind == Isabelle_Process.Kind.STATUS) {
   123         // global status message
   121         // global status message
   124         result.body match {
   122         result.body match {
   125 
   123 
   126           // document state assignment
   124           // document state assignment
   237       }
   235       }
   238     }
   236     }
   239   }
   237   }
   240 
   238 
   241 
   239 
       
   240 
       
   241   /** buffered command changes -- delay_first discipline **/
       
   242 
       
   243   private lazy val command_change_buffer = actor {
       
   244     import scala.compat.Platform.currentTime
       
   245 
       
   246     var changed: Set[Command] = Set()
       
   247     var flush_time: Option[Long] = None
       
   248 
       
   249     def flush_timeout: Long =
       
   250       flush_time match {
       
   251         case None => 5000L
       
   252         case Some(time) => (time - currentTime) max 0
       
   253       }
       
   254 
       
   255     def flush()
       
   256     {
       
   257       if (!changed.isEmpty) commands_changed.event(Command_Set(changed))
       
   258       changed = Set()
       
   259       flush_time = None
       
   260     }
       
   261 
       
   262     def invoke()
       
   263     {
       
   264       val now = currentTime
       
   265       flush_time match {
       
   266         case None => flush_time = Some(now + 100)
       
   267         case Some(time) => if (now >= time) flush()
       
   268       }
       
   269     }
       
   270 
       
   271     loop {
       
   272       reactWithin(flush_timeout) {
       
   273         case command: Command => changed += command; invoke()
       
   274         case TIMEOUT => flush()
       
   275         case bad => System.err.println("command_change_buffer: ignoring bad message " + bad)
       
   276       }
       
   277     }
       
   278   }
       
   279 
       
   280   def indicate_command_change(command: Command)
       
   281   {
       
   282     command_change_buffer ! command
       
   283   }
       
   284 
       
   285 
   242   /* main methods */
   286   /* main methods */
   243 
   287 
   244   def start(timeout: Int, args: List[String]): Option[String] =
   288   def start(timeout: Int, args: List[String]): Option[String] =
   245     (session_actor !? Start(timeout, args)).asInstanceOf[Option[String]]
   289     (session_actor !? Start(timeout, args)).asInstanceOf[Option[String]]
   246 
   290