postpone changes in intermediate state between remove_versions/removed_versions, which is important for handle_change to refer to defined items on prover side;
authorwenzelm
Sun, 17 Aug 2014 16:05:43 +0200
changeset 57976 bf99106b6672
parent 57975 c657c68a60ab
child 57977 113b43b84412
postpone changes in intermediate state between remove_versions/removed_versions, which is important for handle_change to refer to defined items on prover side;
src/Pure/PIDE/document.scala
src/Pure/PIDE/session.scala
--- a/src/Pure/PIDE/document.scala	Fri Aug 15 13:39:59 2014 +0200
+++ b/src/Pure/PIDE/document.scala	Sun Aug 17 16:05:43 2014 +0200
@@ -499,7 +499,9 @@
     /*commands with markup produced by other commands (imm_succs)*/
     val commands_redirection: Graph[Document_ID.Command, Unit] = Graph.long,
     /*explicit (linear) history*/
-    val history: History = History.init)
+    val history: History = History.init,
+    /*intermediate state between remove_versions/removed_versions*/
+    val removing_versions: Boolean = false)
   {
     private def fail[A]: A = throw new State.Fail(this)
 
@@ -620,13 +622,14 @@
       copy(history = history + change)
     }
 
-    def prune_history(retain: Int = 0): (List[Version], State) =
+    def remove_versions(retain: Int = 0): (List[Version], State) =
     {
       history.prune(is_stable, retain) match {
         case Some((dropped, history1)) =>
-          val dropped_versions = dropped.map(change => change.version.get_finished)
-          val state1 = copy(history = history1)
-          (dropped_versions, state1)
+          val old_versions = dropped.map(change => change.version.get_finished)
+          val removing = !old_versions.isEmpty
+          val state1 = copy(history = history1, removing_versions = removing)
+          (old_versions, state1)
         case None => fail
       }
     }
@@ -661,7 +664,8 @@
         commands = commands1,
         execs = execs1,
         commands_redirection = commands_redirection.restrict(commands1.isDefinedAt(_)),
-        assignments = assignments1)
+        assignments = assignments1,
+        removing_versions = false)
     }
 
     private def command_states_self(version: Version, command: Command)
--- a/src/Pure/PIDE/session.scala	Fri Aug 15 13:39:59 2014 +0200
+++ b/src/Pure/PIDE/session.scala	Sun Aug 17 16:05:43 2014 +0200
@@ -52,6 +52,8 @@
     doc_edits: List[Document.Edit_Command],
     version: Document.Version)
 
+  case object Change_Flush
+
 
   /* events */
 
@@ -320,11 +322,10 @@
 
     def store(change: Session.Change): Unit = synchronized { postponed ::= change }
 
-    def flush(): Unit = synchronized {
-      val state = global_state.value
+    def flush(state: Document.State): List[Session.Change] = synchronized {
       val (assigned, unassigned) = postponed.partition(change => state.is_assigned(change.previous))
       postponed = unassigned
-      assigned.reverseIterator.foreach(change => manager.send(change))
+      assigned.reverse
     }
   }
 
@@ -448,9 +449,9 @@
                     try {
                       val cmds = global_state.change_result(_.assign(id, update))
                       change_buffer.invoke(true, cmds)
+                      manager.send(Session.Change_Flush)
                     }
                     catch { case _: Document.State.Fail => bad_output() }
-                    postponed_changes.flush()
                   case _ => bad_output()
                 }
                 delay_prune.invoke()
@@ -460,6 +461,7 @@
                   case Protocol.Removed(removed) =>
                     try {
                       global_state.change(_.removed_versions(removed))
+                      manager.send(Session.Change_Flush)
                     }
                     catch { case _: Document.State.Fail => bad_output() }
                   case _ => bad_output()
@@ -532,7 +534,7 @@
 
           case Prune_History =>
             if (prover.defined) {
-              val old_versions = global_state.change_result(_.prune_history(prune_size))
+              val old_versions = global_state.change_result(_.remove_versions(prune_size))
               if (!old_versions.isEmpty) prover.get.remove_versions(old_versions)
             }
 
@@ -557,10 +559,16 @@
             prover.get.protocol_command(name, args:_*)
 
           case change: Session.Change if prover.defined =>
-            if (global_state.value.is_assigned(change.previous))
+            val state = global_state.value
+            if (!state.removing_versions && state.is_assigned(change.previous))
               handle_change(change)
             else postponed_changes.store(change)
 
+          case Session.Change_Flush if prover.defined =>
+            val state = global_state.value
+            if (!state.removing_versions)
+              postponed_changes.flush(state).foreach(handle_change(_))
+
           case bad =>
             if (verbose) Output.warning("Ignoring bad message: " + bad.toString)
         }