replaced outdated flag by update_time (multithreading-safe presentation order);
authorwenzelm
Fri, 03 Aug 2007 22:33:10 +0200
changeset 24151 255f76dcc16b
parent 24150 ed724867099a
child 24152 63cc746667a0
replaced outdated flag by update_time (multithreading-safe presentation order);
src/Pure/Thy/thy_info.ML
--- a/src/Pure/Thy/thy_info.ML	Fri Aug 03 22:33:09 2007 +0200
+++ b/src/Pure/Thy/thy_info.ML	Fri Aug 03 22:33:10 2007 +0200
@@ -92,18 +92,18 @@
 type master = (Path.T * File.ident) * (Path.T * File.ident) option;
 
 type deps =
-  {outdated: bool,              (*entry considered outdated*)
+  {update_time: int,            (*symbolic time of last update; < 0 means outdated*)
     master: master option,      (*master dependencies for thy + attached ML file*)
     text: string list,          (*source text for thy*)
     parents: string list,       (*source specification of parents (partially qualified)*)
     files:                      (*auxiliary files: source path, physical path + identifier*)
       (Path.T * (Path.T * File.ident) option) list};
 
-fun make_deps outdated master text parents files : deps =
-  {outdated = outdated, master = master, text = text, parents = parents, files = files};
+fun make_deps update_time master text parents files : deps =
+  {update_time = update_time, master = master, text = text, parents = parents, files = files};
 
 fun init_deps master text parents files =
-  SOME (make_deps true master text parents (map (rpair NONE) files));
+  SOME (make_deps ~1 master text parents (map (rpair NONE) files));
 
 fun master_idents (NONE: master option) = []
   | master_idents (SOME ((_, thy_id), NONE)) = [thy_id]
@@ -235,20 +235,20 @@
   in files end;
 
 
-(* maintain 'outdated' flag *)
+(* maintain update_time *)
 
 local
 
 fun is_outdated name =
   (case lookup_deps name of
-    SOME (SOME {outdated, ...}) => outdated
+    SOME (SOME {update_time, ...}) => update_time < 0
   | _ => false);
 
 fun outdate_thy name =
   if is_finished name orelse is_outdated name then ()
   else CRITICAL (fn () =>
-   (change_deps name (Option.map (fn {outdated = _, master, text, parents, files} =>
-    make_deps true master text parents files)); perform Outdate name));
+   (change_deps name (Option.map (fn {master, text, parents, files, ...} =>
+    make_deps ~1 master text parents files)); perform Outdate name));
 
 fun check_unfinished name =
   if is_finished name then (warning (loader_msg "tried to touch finished theory" [name]); NONE)
@@ -271,11 +271,12 @@
 
 local
 
-fun provide path name info (deps as SOME {outdated, master, text, parents, files}) =
+fun provide path name info (deps as SOME {update_time, master, text, parents, files}) =
      (if AList.defined (op =) files path then ()
       else warning (loader_msg "undeclared dependency of theory" [name] ^
         " on file: " ^ quote (Path.implode path));
-      SOME (make_deps outdated master text parents (AList.update (op =) (path, SOME info) files)))
+      SOME (make_deps update_time master text parents
+        (AList.update (op =) (path, SOME info) files)))
   | provide _ _ _ NONE = NONE;
 
 fun run_file path =
@@ -310,7 +311,7 @@
 fun required_by _ [] = ""
   | required_by s initiators = s ^ "(required by " ^ show_path (rev initiators) ^ ")";
 
-fun load_thy ml time initiators dir name =
+fun load_thy ml time upd_time initiators dir name =
   let
     val _ = priority ("Loading theory " ^ quote name ^ required_by " " initiators);
     val (pos, text, files) =
@@ -319,12 +320,16 @@
           (Position.path master_path, text, files)
       | _ => error (loader_msg "corrupted dependency information" [name]));
     val _ = touch_thy name;
+    val _ = CRITICAL (fn () =>
+      change_deps name (Option.map (fn {master, text, parents, files, ...} =>
+        make_deps upd_time master text parents files)));
     val _ = ThyLoad.load_thy dir name pos text ml (time orelse ! Output.timing);
     val _ = check_files name;
   in
     CRITICAL (fn () =>
      (change_deps name
-        (Option.map (fn {master, parents, files, ...} => make_deps false master [] parents files));
+        (Option.map (fn {update_time, master, parents, files, ...} =>
+          make_deps update_time master [] parents files));
       perform Update name))
   end;
 
@@ -347,7 +352,7 @@
   | NONE =>
       let val {master, text, imports = parents, uses = files} = ThyLoad.deps_thy dir name ml
       in (false, init_deps (SOME master) text parents files, parents) end
-  | SOME (deps as SOME {outdated, master, text, parents, files}) =>
+  | SOME (deps as SOME {update_time, master, text, parents, files}) =>
       if not strict andalso can get_theory name then (true, deps, parents)
       else
         let val master' = SOME (ThyLoad.check_thy dir name ml) in
@@ -359,8 +364,9 @@
           else
             let
               val checked_files = map (check_ml master') files;
-              val current = not outdated andalso forall (is_some o snd) checked_files;
-              val deps' = SOME (make_deps (not current) master' text parents checked_files);
+              val current = update_time >= 0 andalso forall (is_some o snd) checked_files;
+              val update_time' = if current then update_time else ~1;
+              val deps' = SOME (make_deps update_time' master' text parents checked_files);
             in (current, deps', parents) end
         end);
 
@@ -391,12 +397,13 @@
               (name :: initiators) (Path.append dir (master_dir' deps)) parents tasks;
 
           val all_current = current andalso parents_current;
-          val thy = if all_current then SOME (get_theory name) else NONE;
-          val _ = change_thys (new_deps name parent_names (deps, thy));
+          val theory = if all_current then SOME (get_theory name) else NONE;
+          val _ = change_thys (new_deps name parent_names (deps, theory));
 
+          val upd_time = serial ();
           val tasks_graph'' = tasks_graph' |> new_deps name parent_names
            (if all_current then Task.Finished
-            else Task.Task (fn () => load_thy ml time initiators dir' name));
+            else Task.Task (fn () => load_thy ml time upd_time initiators dir' name));
           val tasks_len'' = if all_current then tasks_len' else tasks_len' + 1;
         in (all_current, (tasks_graph'', tasks_len'')) end)
   end;
@@ -420,7 +427,7 @@
 fun next_task G =
   let
     val tasks = Graph.minimals G |> map (fn name =>
-      (name, (Graph.get_node G name, length (Graph.imm_succs G name))))
+      (name, (Graph.get_node G name, length (Graph.imm_succs G name))));
     val finished = filter (Task.is_finished o fst o snd) tasks;
   in
     if not (null finished) then next_task (Graph.del_nodes (map fst finished) G)
@@ -498,20 +505,21 @@
       ML_Context.set_context (SOME (Context.Theory (get_theory (List.last parent_names)))));
     val _ = check_uses name uses;
 
-    val theory =
-      Theory.begin_theory name (map get_theory parent_names)
-      |> Present.begin_theory dir uses;
+    val theory = Theory.begin_theory name (map get_theory parent_names);
 
     val deps =
       if known_thy name then get_deps name
       else init_deps NONE [] parents (map #1 uses);
     val _ = change_thys (new_deps name parent_names (deps, NONE));
 
+    val update_time = (case deps of NONE => 0 | SOME {update_time, ...} => update_time);
+    val theory' = Present.begin_theory update_time dir uses theory;
+
     val uses_now = map_filter (fn (x, true) => SOME x | _ => NONE) uses;
-    val ((), theory') =
-      ML_Context.pass_context (Context.Theory theory) (List.app (load_file false)) uses_now
+    val ((), theory'') =
+      ML_Context.pass_context (Context.Theory theory') (List.app (load_file false)) uses_now
       ||> Context.the_theory;
-  in theory' end;
+  in theory'' end;
 
 fun end_theory theory =
   let
@@ -532,10 +540,11 @@
     val _ = touch_thy name;
     val files = check_files name;
     val master = #master (ThyLoad.deps_thy Path.current name false);
+    val upd_time = serial ();
   in
     CRITICAL (fn () =>
      (change_deps name
-        (Option.map (fn {parents, ...} => make_deps false (SOME master) [] parents files));
+        (Option.map (fn {parents, ...} => make_deps upd_time (SOME master) [] parents files));
       perform Update name))
   end;