src/Pure/System/session.scala
changeset 52111 1fd184eaa310
parent 52084 573e80625c78
child 52113 2d2b049429f3
equal deleted inserted replaced
52108:06db08182c4b 52111:1fd184eaa310
    35   case object Startup extends Phase  // transient
    35   case object Startup extends Phase  // transient
    36   case object Failed extends Phase
    36   case object Failed extends Phase
    37   case object Ready extends Phase
    37   case object Ready extends Phase
    38   case object Shutdown extends Phase  // transient
    38   case object Shutdown extends Phase  // transient
    39   //}}}
    39   //}}}
       
    40 
       
    41 
       
    42   /* protocol handlers */
       
    43 
       
    44   type Prover = Isabelle_Process with Protocol
       
    45 
       
    46   abstract class Protocol_Handler
       
    47   {
       
    48     def stop(prover: Prover): Unit = {}
       
    49     val functions: Map[String, (Prover, Isabelle_Process.Output) => Boolean]
       
    50   }
       
    51 
       
    52   class Protocol_Handlers(
       
    53     handlers: Map[String, Session.Protocol_Handler] = Map.empty,
       
    54     functions: Map[String, Isabelle_Process.Output => Boolean] = Map.empty)
       
    55   {
       
    56     def add(prover: Prover, name: String): Protocol_Handlers =
       
    57     {
       
    58       val (handlers1, functions1) =
       
    59         handlers.get(name) match {
       
    60           case Some(old_handler) =>
       
    61             System.err.println("Redefining protocol handler: " + name)
       
    62             old_handler.stop(prover)
       
    63             (handlers - name, functions -- old_handler.functions.keys)
       
    64           case None => (handlers, functions)
       
    65         }
       
    66 
       
    67       val (handlers2, functions2) =
       
    68         try {
       
    69           val new_handler = Class.forName(name).newInstance.asInstanceOf[Protocol_Handler]
       
    70           val new_functions =
       
    71             for ((a, f) <- new_handler.functions.toList) yield
       
    72               (a, (output: Isabelle_Process.Output) => f(prover, output))
       
    73 
       
    74           val dups = for ((a, _) <- new_functions if functions1.isDefinedAt(a)) yield a
       
    75           if (!dups.isEmpty) error("Duplicate protocol functions: " + commas_quote(dups))
       
    76 
       
    77           (handlers1 + (name -> new_handler), functions1 ++ new_functions)
       
    78         }
       
    79         catch {
       
    80           case exn: Throwable =>
       
    81             System.err.println("Failed to initialize protocol handler: " +
       
    82               name + "\n" + Exn.message(exn))
       
    83             (handlers1, functions1)
       
    84         }
       
    85 
       
    86       new Protocol_Handlers(handlers2, functions2)
       
    87     }
       
    88 
       
    89     def invoke(output: Isabelle_Process.Output): Boolean =
       
    90       output.properties match {
       
    91         case Markup.Function(a) if functions.isDefinedAt(a) =>
       
    92           try { functions(a)(output) }
       
    93           catch {
       
    94             case exn: Throwable =>
       
    95               System.err.println("Failed invocation of protocol function: " +
       
    96                 quote(a) + "\n" + Exn.message(exn))
       
    97             false
       
    98           }
       
    99         case _ => false
       
   100       }
       
   101   }
    40 }
   102 }
    41 
   103 
    42 
   104 
    43 class Session(val thy_load: Thy_Load)
   105 class Session(val thy_load: Thy_Load)
    44 {
   106 {
   174   private case class Change(
   236   private case class Change(
   175     doc_edits: List[Document.Edit_Command],
   237     doc_edits: List[Document.Edit_Command],
   176     previous: Document.Version,
   238     previous: Document.Version,
   177     version: Document.Version)
   239     version: Document.Version)
   178   private case class Messages(msgs: List[Isabelle_Process.Message])
   240   private case class Messages(msgs: List[Isabelle_Process.Message])
   179   private case class Finished_Scala(id: String, tag: Invoke_Scala.Tag.Value, result: String)
       
   180   private case class Update_Options(options: Options)
   241   private case class Update_Options(options: Options)
   181 
   242 
   182   private val (_, session_actor) = Simple_Thread.actor("session_actor", daemon = true)
   243   private val (_, session_actor) = Simple_Thread.actor("session_actor", daemon = true)
   183   {
   244   {
   184     val this_actor = self
   245     val this_actor = self
   185 
   246 
       
   247     var protocol_handlers = new Session.Protocol_Handlers()
       
   248 
   186     var prune_next = System.currentTimeMillis() + prune_delay.ms
   249     var prune_next = System.currentTimeMillis() + prune_delay.ms
   187 
       
   188     var futures = Map.empty[String, java.util.concurrent.Future[Unit]]
       
   189 
   250 
   190 
   251 
   191     /* buffered prover messages */
   252     /* buffered prover messages */
   192 
   253 
   193     object receiver
   254     object receiver
   220       timer.schedule(new TimerTask { def run = flush }, message_delay.ms, message_delay.ms)
   281       timer.schedule(new TimerTask { def run = flush }, message_delay.ms, message_delay.ms)
   221 
   282 
   222       def cancel() { timer.cancel() }
   283       def cancel() { timer.cancel() }
   223     }
   284     }
   224 
   285 
   225     var prover: Option[Isabelle_Process with Protocol] = None
   286     var prover: Option[Session.Prover] = None
   226 
   287 
   227 
   288 
   228     /* delayed command changes */
   289     /* delayed command changes */
   229 
   290 
   230     object delay_commands_changed
   291     object delay_commands_changed
   316         catch {
   377         catch {
   317           case _: Document.State.Fail => bad_output()
   378           case _: Document.State.Fail => bad_output()
   318         }
   379         }
   319       }
   380       }
   320 
   381 
   321       output.properties match {
   382       if (output.is_protocol) {
   322 
   383         val handled = protocol_handlers.invoke(output)
   323         case Position.Id(state_id) if !output.is_protocol =>
   384         if (!handled) {
   324           accumulate(state_id, output.message)
   385           output.properties match {
   325 
   386             case Markup.Protocol_Handler(name) =>
   326         case Protocol.Command_Timing(state_id, timing) if output.is_protocol =>
   387               protocol_handlers = protocol_handlers.add(prover.get, name)
   327           val message = XML.elem(Markup.STATUS, List(XML.Elem(Markup.Timing(timing), Nil)))
   388 
   328           accumulate(state_id, prover.get.xml_cache.elem(message))
   389             case Protocol.Command_Timing(state_id, timing) =>
   329 
   390               val message = XML.elem(Markup.STATUS, List(XML.Elem(Markup.Timing(timing), Nil)))
   330         case Markup.Assign_Execs if output.is_protocol =>
   391               accumulate(state_id, prover.get.xml_cache.elem(message))
   331           XML.content(output.body) match {
   392 
   332             case Protocol.Assign(id, assign) =>
   393             case Markup.Assign_Execs =>
   333               try {
   394               XML.content(output.body) match {
   334                 val cmds = global_state >>> (_.assign(id, assign))
   395                 case Protocol.Assign(id, assign) =>
   335                 delay_commands_changed.invoke(true, cmds)
   396                   try {
       
   397                     val cmds = global_state >>> (_.assign(id, assign))
       
   398                     delay_commands_changed.invoke(true, cmds)
       
   399                   }
       
   400                   catch { case _: Document.State.Fail => bad_output() }
       
   401                 case _ => bad_output()
   336               }
   402               }
   337               catch { case _: Document.State.Fail => bad_output() }
   403               // FIXME separate timeout event/message!?
       
   404               if (prover.isDefined && System.currentTimeMillis() > prune_next) {
       
   405                 val old_versions = global_state >>> (_.prune_history(prune_size))
       
   406                 if (!old_versions.isEmpty) prover.get.remove_versions(old_versions)
       
   407                 prune_next = System.currentTimeMillis() + prune_delay.ms
       
   408               }
       
   409 
       
   410             case Markup.Removed_Versions =>
       
   411               XML.content(output.body) match {
       
   412                 case Protocol.Removed(removed) =>
       
   413                   try {
       
   414                     global_state >> (_.removed_versions(removed))
       
   415                   }
       
   416                   catch { case _: Document.State.Fail => bad_output() }
       
   417                 case _ => bad_output()
       
   418               }
       
   419 
       
   420             case Markup.ML_Statistics(props) =>
       
   421               statistics.event(Session.Statistics(props))
       
   422 
       
   423             case Markup.Task_Statistics(props) =>
       
   424               // FIXME
       
   425 
   338             case _ => bad_output()
   426             case _ => bad_output()
   339           }
   427           }
   340           // FIXME separate timeout event/message!?
   428         }
   341           if (prover.isDefined && System.currentTimeMillis() > prune_next) {
   429       }
   342             val old_versions = global_state >>> (_.prune_history(prune_size))
   430       else {
   343             if (!old_versions.isEmpty) prover.get.remove_versions(old_versions)
   431         output.properties match {
   344             prune_next = System.currentTimeMillis() + prune_delay.ms
   432           case Position.Id(state_id) =>
   345           }
   433             accumulate(state_id, output.message)
   346 
   434 
   347         case Markup.Removed_Versions if output.is_protocol =>
   435           case _ if output.is_init =>
   348           XML.content(output.body) match {
   436             phase = Session.Ready
   349             case Protocol.Removed(removed) =>
   437 
   350               try {
   438           case Markup.Return_Code(rc) if output.is_exit =>
   351                 global_state >> (_.removed_versions(removed))
   439             if (rc == 0) phase = Session.Inactive
   352               }
   440             else phase = Session.Failed
   353               catch { case _: Document.State.Fail => bad_output() }
   441 
   354             case _ => bad_output()
   442           case _ => bad_output()
   355           }
   443         }
   356 
       
   357         case Markup.Invoke_Scala(name, id) if output.is_protocol =>
       
   358           futures += (id ->
       
   359             default_thread_pool.submit(() =>
       
   360               {
       
   361                 val arg = XML.content(output.body)
       
   362                 val (tag, result) = Invoke_Scala.method(name, arg)
       
   363                 this_actor ! Finished_Scala(id, tag, result)
       
   364               }))
       
   365 
       
   366         case Markup.Cancel_Scala(id) if output.is_protocol =>
       
   367           futures.get(id) match {
       
   368             case Some(future) =>
       
   369               future.cancel(true)
       
   370               this_actor ! Finished_Scala(id, Invoke_Scala.Tag.INTERRUPT, "")
       
   371             case None =>
       
   372           }
       
   373 
       
   374         case Markup.ML_Statistics(props) if output.is_protocol =>
       
   375           statistics.event(Session.Statistics(props))
       
   376 
       
   377         case Markup.Task_Statistics(props) if output.is_protocol =>
       
   378           // FIXME
       
   379 
       
   380         case _ if output.is_init =>
       
   381           phase = Session.Ready
       
   382 
       
   383         case Markup.Return_Code(rc) if output.is_exit =>
       
   384           if (rc == 0) phase = Session.Inactive
       
   385           else phase = Session.Failed
       
   386 
       
   387         case _ => bad_output()
       
   388       }
   444       }
   389     }
   445     }
   390     //}}}
   446     //}}}
   391 
   447 
   392 
   448 
   453 
   509 
   454         case change: Change
   510         case change: Change
   455         if prover.isDefined && global_state().is_assigned(change.previous) =>
   511         if prover.isDefined && global_state().is_assigned(change.previous) =>
   456           handle_change(change)
   512           handle_change(change)
   457 
   513 
   458         case Finished_Scala(id, tag, result) if prover.isDefined =>
       
   459           if (futures.isDefinedAt(id)) {
       
   460             prover.get.invoke_scala(id, tag, result)
       
   461             futures -= id
       
   462           }
       
   463 
       
   464         case bad if !bad.isInstanceOf[Change] =>
   514         case bad if !bad.isInstanceOf[Change] =>
   465           System.err.println("session_actor: ignoring bad message " + bad)
   515           System.err.println("session_actor: ignoring bad message " + bad)
   466       }
   516       }
   467     }
   517     }
   468     //}}}
   518     //}}}