src/Pure/System/session.scala
changeset 39630 44181423183a
parent 39629 08eb2730a8a1
child 39633 26a28110ece5
equal deleted inserted replaced
39629:08eb2730a8a1 39630:44181423183a
    19 
    19 
    20   case object Global_Settings
    20   case object Global_Settings
    21   case object Perspective
    21   case object Perspective
    22   case object Assignment
    22   case object Assignment
    23   case class Commands_Changed(set: Set[Command])
    23   case class Commands_Changed(set: Set[Command])
       
    24 
       
    25   sealed abstract class Phase
       
    26   case object Inactive extends Phase
       
    27   case object Startup extends Phase
       
    28   case object Exit extends Phase
       
    29   case object Ready extends Phase
       
    30   case object Shutdown extends Phase
       
    31   case object Terminated extends Phase
    24 }
    32 }
    25 
    33 
    26 
    34 
    27 class Session(system: Isabelle_System)
    35 class Session(system: Isabelle_System)
    28 {
    36 {
    38   val update_delay = 500
    46   val update_delay = 500
    39 
    47 
    40 
    48 
    41   /* pervasive event buses */
    49   /* pervasive event buses */
    42 
    50 
       
    51   val phase_changed = new Event_Bus[(Session.Phase, Session.Phase)]
    43   val global_settings = new Event_Bus[Session.Global_Settings.type]
    52   val global_settings = new Event_Bus[Session.Global_Settings.type]
    44   val raw_messages = new Event_Bus[Isabelle_Process.Result]
    53   val raw_messages = new Event_Bus[Isabelle_Process.Result]
    45   val commands_changed = new Event_Bus[Session.Commands_Changed]
    54   val commands_changed = new Event_Bus[Session.Commands_Changed]
    46   val perspective = new Event_Bus[Session.Perspective.type]
    55   val perspective = new Event_Bus[Session.Perspective.type]
    47   val assignments = new Event_Bus[Session.Assignment.type]
    56   val assignments = new Event_Bus[Session.Assignment.type]
    96     var finished = false
   105     var finished = false
    97     while (!finished) {
   106     while (!finished) {
    98       receiveWithin(flush_timeout) {
   107       receiveWithin(flush_timeout) {
    99         case command: Command => changed += command; invoke()
   108         case command: Command => changed += command; invoke()
   100         case TIMEOUT => flush()
   109         case TIMEOUT => flush()
   101         case Stop => finished = true
   110         case Stop => finished = true; reply(())
   102         case bad => System.err.println("command_change_buffer: ignoring bad message " + bad)
   111         case bad => System.err.println("command_change_buffer: ignoring bad message " + bad)
   103       }
   112       }
   104     }
   113     }
   105   }
   114   }
   106   //}}}
   115   //}}}
   113   def current_syntax(): Outer_Syntax = syntax
   122   def current_syntax(): Outer_Syntax = syntax
   114 
   123 
   115   @volatile private var reverse_syslog = List[XML.Elem]()
   124   @volatile private var reverse_syslog = List[XML.Elem]()
   116   def syslog(): String = reverse_syslog.reverse.map(msg => XML.content(msg).mkString).mkString("\n")
   125   def syslog(): String = reverse_syslog.reverse.map(msg => XML.content(msg).mkString).mkString("\n")
   117 
   126 
       
   127   @volatile private var _phase: Session.Phase = Session.Inactive
       
   128   def phase = _phase
       
   129   def phase_=(new_phase: Session.Phase)
       
   130   {
       
   131     val old_phase = _phase
       
   132     _phase = new_phase
       
   133     phase_changed.event(old_phase, new_phase)
       
   134   }
       
   135 
   118   private val global_state = new Volatile(Document.State.init)
   136   private val global_state = new Volatile(Document.State.init)
   119   def current_state(): Document.State = global_state.peek()
   137   def current_state(): Document.State = global_state.peek()
   120 
   138 
   121   private case object Interrupt_Prover
   139   private case object Interrupt_Prover
   122   private case class Edit_Version(edits: List[Document.Node_Text_Edit])
   140   private case class Edit_Version(edits: List[Document.Node_Text_Edit])
   123   private case class Started(timeout: Int, args: List[String])
   141   private case class Start(timeout: Int, args: List[String])
   124 
   142 
   125   private val (_, session_actor) = Simple_Thread.actor("session_actor", daemon = true)
   143   private val (_, session_actor) = Simple_Thread.actor("session_actor", daemon = true)
   126   {
   144   {
   127     var prover: Isabelle_Process with Isar_Document = null
   145     var prover: Isabelle_Process with Isar_Document = null
   128 
   146 
   188             val st = global_state.change_yield(_.accumulate(state_id, result.message))
   206             val st = global_state.change_yield(_.accumulate(state_id, result.message))
   189             command_change_buffer ! st.command
   207             command_change_buffer ! st.command
   190           }
   208           }
   191           catch { case _: Document.State.Fail => bad_result(result) }
   209           catch { case _: Document.State.Fail => bad_result(result) }
   192         case _ =>
   210         case _ =>
   193           if (result.is_exit) prover = null  // FIXME ??
   211           if (result.is_syslog) {
   194           else if (result.is_syslog) reverse_syslog ::= result.message
   212             reverse_syslog ::= result.message
       
   213             if (result.is_ready) phase = Session.Ready
       
   214             else if (result.is_exit) phase = Session.Exit
       
   215           }
   195           else if (result.is_stdout) { }
   216           else if (result.is_stdout) { }
   196           else if (result.is_status) {
   217           else if (result.is_status) {
   197             result.body match {
   218             result.body match {
   198               case List(Isar_Document.Assign(id, edits)) =>
   219               case List(Isar_Document.Assign(id, edits)) =>
   199                 try {
   220                 try {
   211         }
   232         }
   212     }
   233     }
   213     //}}}
   234     //}}}
   214 
   235 
   215 
   236 
   216     /* prover startup */
   237     /* main loop */
   217 
       
   218     def startup_error(): String =
       
   219     {
       
   220       val buf = new StringBuilder
       
   221       while (
       
   222         receiveWithin(0) {
       
   223           case result: Isabelle_Process.Result =>
       
   224             if (result.is_system) {
       
   225               for (text <- XML.content(result.message))
       
   226                 buf.append(text)
       
   227             }
       
   228             true
       
   229           case TIMEOUT => false
       
   230         }) {}
       
   231       buf.toString
       
   232     }
       
   233 
       
   234     def prover_startup(timeout: Int): Option[String] =
       
   235     {
       
   236       receiveWithin(timeout) {
       
   237         case result: Isabelle_Process.Result if result.is_init =>
       
   238           handle_result(result)
       
   239           while (receive {
       
   240             case result: Isabelle_Process.Result =>
       
   241               handle_result(result); !result.is_ready
       
   242             }) {}
       
   243           None
       
   244 
       
   245         case result: Isabelle_Process.Result if result.is_exit =>
       
   246           handle_result(result)
       
   247           Some(startup_error())
       
   248 
       
   249         case TIMEOUT =>  // FIXME clarify
       
   250           prover.terminate; Some(startup_error())
       
   251       }
       
   252     }
       
   253 
       
   254 
       
   255     /* main loop */  // FIXME proper shutdown
       
   256 
   238 
   257     var finished = false
   239     var finished = false
   258     while (!finished) {
   240     while (!finished) {
   259       receive {
   241       receive {
   260         case Interrupt_Prover =>
   242         case Interrupt_Prover =>
   261           if (prover != null) prover.interrupt
   243           if (prover != null) prover.interrupt
   262 
   244 
   263         case Edit_Version(edits) =>
   245         case Edit_Version(edits) if prover != null =>
   264           val previous = global_state.peek().history.tip.current
   246           val previous = global_state.peek().history.tip.current
   265           val result = Future.fork { Thy_Syntax.text_edits(Session.this, previous.join, edits) }
   247           val result = Future.fork { Thy_Syntax.text_edits(Session.this, previous.join, edits) }
   266           val change = global_state.change_yield(_.extend_history(previous, edits, result))
   248           val change = global_state.change_yield(_.extend_history(previous, edits, result))
   267 
   249 
   268           val this_actor = self
   250           val this_actor = self
   270             assignments.await { global_state.peek().is_assigned(previous.get_finished) }
   252             assignments.await { global_state.peek().is_assigned(previous.get_finished) }
   271             this_actor ! change })
   253             this_actor ! change })
   272 
   254 
   273           reply(())
   255           reply(())
   274 
   256 
   275         case change: Document.Change if prover != null =>
   257         case change: Document.Change if prover != null => handle_change(change)
   276           handle_change(change)
   258 
   277 
   259         case result: Isabelle_Process.Result => handle_result(result)
   278         case result: Isabelle_Process.Result =>
   260 
   279           handle_result(result)
   261         case Start(timeout, args) if prover == null =>
   280 
   262           phase = Session.Startup
   281         case Started(timeout, args) =>
   263           prover = new Isabelle_Process(system, timeout, self, args:_*) with Isar_Document
   282           if (prover == null) {
   264 
   283             prover = new Isabelle_Process(system, timeout, self, args:_*) with Isar_Document
   265         case Stop if phase == Session.Ready =>
   284             val origin = sender
   266           global_state.change(_ => Document.State.init)  // FIXME event bus!?
   285             val opt_err = prover_startup(timeout + 500)
   267           phase = Session.Shutdown
   286             if (opt_err.isDefined) prover = null
   268           prover.terminate
   287             origin ! opt_err
   269           phase = Session.Terminated
   288           }
   270           finished = true
   289           else reply(None)
   271           reply(())
   290 
       
   291         case Stop => // FIXME synchronous!?
       
   292           if (prover != null) {
       
   293             global_state.change(_ => Document.State.init)
       
   294             prover.terminate
       
   295             prover = null
       
   296           }
       
   297 
       
   298         case TIMEOUT =>  // FIXME clarify
       
   299 
   272 
   300         case bad if prover != null =>
   273         case bad if prover != null =>
   301           System.err.println("session_actor: ignoring bad message " + bad)
   274           System.err.println("session_actor: ignoring bad message " + bad)
   302       }
   275       }
   303     }
   276     }
   305 
   278 
   306 
   279 
   307 
   280 
   308   /** main methods **/
   281   /** main methods **/
   309 
   282 
   310   def started(timeout: Int, args: List[String]): Option[String] =
   283   def start(timeout: Int, args: List[String]) { session_actor ! Start(timeout, args) }
   311     (session_actor !? Started(timeout, args)).asInstanceOf[Option[String]]
   284 
   312 
   285   def stop() { command_change_buffer !? Stop; session_actor !? Stop }
   313   def stop() { command_change_buffer ! Stop; session_actor ! Stop }
       
   314 
   286 
   315   def interrupt() { session_actor ! Interrupt_Prover }
   287   def interrupt() { session_actor ! Interrupt_Prover }
   316 
   288 
   317   def edit_version(edits: List[Document.Node_Text_Edit]) { session_actor !? Edit_Version(edits) }
   289   def edit_version(edits: List[Document.Node_Text_Edit]) { session_actor !? Edit_Version(edits) }
   318 
   290