@@ -104,73 +104,88 @@ let as_string = function
104104 | `String s -> s
105105 | _ -> failwith " Not a string"
106106
107- let layout ~duration (ring : Ring.t ) =
107+ (* Walk the tree rooted at [i], calculating heights and positions.
108+ Note: visited items have their [y] fields set to their position relative to
109+ their parent. This gets turned into an absolute position later. *)
110+ let rec layout_item ~duration (i : item ) =
111+ i.y < - 0 ;
112+ i.height < - 1 ;
113+ i.end_cc_label < - None ;
114+ let intervals = ref [] in
115+ (* Position CCs at the same place as [i]. *)
116+ i.events |> Array. iter (fun (ts , e ) ->
117+ match e with
118+ | Log _ | Error _ ->
119+ if i.end_cc_label = None then (
120+ i.end_cc_label < - Some ts;
121+ )
122+ | Add_fiber _ -> ()
123+ | Create_cc (_ , child ) ->
124+ if debug_layout then Fmt. epr " %d creates cc %d (%a)@." i.id child.id Fmt. (option string ) child.name;
125+ if i.end_cc_label = None then (
126+ i.end_cc_label < - Some ts;
127+ );
128+ layout_item ~duration child;
129+ i.height < - max i.height child.height;
130+ let stop = Option. value child.end_time ~default: duration in
131+ intervals := { Itv. value = child; start = ts; stop } :: ! intervals;
132+ );
133+ if i.end_cc_label = None then i.end_cc_label < - i.end_time;
134+ let n_ccs = List. length ! intervals in
135+ (* Position fibers where there is space, not overlapping CCs or other fibers. *)
136+ i.events |> Array. iter (fun (ts , e ) ->
137+ match e with
138+ | Log _ | Error _ | Create_cc _ -> ()
139+ | Add_fiber { parent; child } ->
140+ if debug_layout then Fmt. epr " %d gets fiber %d, created by %d@." i.id child.id parent;
141+ let stop = Option. value child.end_time ~default: duration in
142+ intervals := { Itv. value = child; start = ts; stop } :: ! intervals;
143+ );
144+ let intervals = List. rev ! intervals in
145+ let itv = Itv. create intervals in
146+ let height = ref i.height in
147+ intervals |> List. to_seq |> Seq. drop n_ccs |> Seq. iter (fun (interval : _ Itv.interval ) ->
148+ let space = Space. create 1 in
149+ let adjust other = Space. mark_range space other.y (other.y + other.height) in
150+ Itv. iter_overlaps adjust interval.start interval.stop itv;
151+ let f = interval.Itv. value in
152+ layout_item ~duration f;
153+ f.y < - Space. first_free space f.height;
154+ height := max ! height (f.y + f.height);
155+ );
156+ i.height < - ! height
157+
158+ (* Walk the tree rooted at [i] converting relative [y] values to absolute ones,
159+ using [parent] for zero. *)
160+ let rec make_y_absolute i parent =
161+ i.y < - i.y + parent;
162+ if debug_layout then Fmt. epr " %d is at %d (height %d)@." i.id i.y i.height;
163+ i.events |> Array. iter (fun (_ts , e ) ->
164+ match e with
165+ | Log _ | Error _ -> ()
166+ | Add_fiber { parent = _; child }
167+ | Create_cc (_ , child ) -> make_y_absolute child i.y
168+ )
169+
170+ let layout_ring ~duration (ring : Ring.t ) =
108171 let max_y = ref 1 in
109- let rec visit ~y (i : item ) =
110- if debug_layout then Fmt. epr " %d is at %d@." i.id y;
111- i.y < - y;
112- i.height < - 1 ;
113- i.end_cc_label < - None ;
114- let intervals = ref [] in
115- i.events |> Array. iter (fun (ts , e ) ->
116- match e with
117- | Log _ | Error _ ->
118- if i.end_cc_label = None then (
119- i.end_cc_label < - Some ts;
120- )
121- | Add_fiber _ -> ()
122- | Create_cc (_ , child ) ->
123- if debug_layout then Fmt. epr " %d creates cc %d (%a)@." i.id child.id Fmt. (option string ) child.name;
124- if i.end_cc_label = None then (
125- i.end_cc_label < - Some ts;
126- );
127- visit ~y child;
128- i.height < - max i.height child.height;
129- let stop = Option. value child.end_time ~default: duration in
130- intervals := { Itv. value = child; start = ts; stop } :: ! intervals;
131- );
132- if i.end_cc_label = None then i.end_cc_label < - i.end_time;
133- let start_fibers = List. length ! intervals in
134- i.events |> Array. iter (fun (ts , e ) ->
135- match e with
136- | Log _ | Error _ | Create_cc _ -> ()
137- | Add_fiber { parent; child } ->
138- if debug_layout then Fmt. epr " %d gets fiber %d, created by %d@." i.id child.id parent;
139- let stop = Option. value child.end_time ~default: duration in
140- intervals := { Itv. value = child; start = ts; stop } :: ! intervals;
141- );
142- let intervals = List. rev ! intervals in
143- let itv = Itv. create intervals in
144- let height = ref i.height in
145- intervals |> List. to_seq |> Seq. drop start_fibers |> Seq. iter (fun (interval : _ Itv.interval ) ->
146- let y = ref (i.y + 1 ) in
147- let adjust other =
148- y := max ! y (other.y + other.height);
149- in
150- Itv. iter_overlaps adjust interval.start interval.stop itv;
151- let f = interval.Itv. value in
152- visit ~y: ! y f;
153- height := max ! height (f.y - i.y + f.height);
154- );
155- i.height < - ! height;
156- max_y := max ! max_y i.y;
157- if debug_layout then Fmt. epr " %d is at %d+%d@." i.id y i.height;
158- in
159172 let visit_domain root =
160173 root.Ring. cc |> Option. iter @@ fun (_ts , (i : item )) ->
161- i.y < - ring.y + 1 ;
174+ i.y < - 1 ;
162175 i.height < - 1 ;
163176 i.end_cc_label < - None ;
164177 i.events |> Array. iter (fun (_ts , e ) ->
165178 match e with
166179 | Log _ | Error _ | Create_cc _ -> ()
167180 | Add_fiber { parent = _ ; child } ->
168- visit ~y: (ring.y + i.height) child;
169- i.height < - child.y - ring .y + child.height;
181+ layout_item ~duration child;
182+ i.height < - max i.height (child .y + child.height) ;
170183 if i.end_cc_label = None then (
171184 i.end_cc_label < - child.end_cc_label;
172185 );
173186 );
187+ make_y_absolute i ring.y;
188+ max_y := max ! max_y (i.y + i.height - 1 );
174189 in
175190 List. iter visit_domain ring.roots;
176191 ring.height < - (! max_y + 1 ) - ring.y
@@ -233,7 +248,7 @@ let of_trace (trace : Trace.t) =
233248 let y = ref 0 in
234249 rings |> Trace.Rings. iter (fun _ (ring : Ring.t ) ->
235250 ring.y < - ! y;
236- layout ring ~duration ;
251+ layout_ring ring ~duration ;
237252 y := ! y + ring.height;
238253 );
239254 let height = ! y in
0 commit comments