treeQueue: MonitoredQueue.MQ ← MonitoredQueue.Create[];
FreeTree:
PUBLIC
PROC [root: RefBranchNode] = {
IF root=NIL OR root.deleted THEN RETURN;
root.deleted ← TRUE;
FOR event: EditEvent ← editEvent.next, event.next UNTIL event = editEvent DO
FOR sub: UndoEvent.SubEvent ← editEvent.undo.subevents, sub.next UNTIL sub=NIL DO
IF sub.undoRef # NIL THEN WITH sub.undoRef SELECT FROM
x: REF UndoEvent.Change.ChangingText => IF x.root = root THEN RETURN;
x: REF UndoEvent.Change.ChangingProp => IF x.root = root THEN RETURN;
x: REF UndoEvent.Change.MovingNodes => IF x.destRoot = root OR x.sourceRoot = root THEN RETURN;
x: REF UndoEvent.Change.NodeNesting => IF x.root = root THEN RETURN;
x: REF UndoEvent.Change.InsertingNode => IF x.root = root THEN RETURN;
ENDCASE;
ENDLOOP;
ENDLOOP;
MonitoredQueue.Add[root, treeQueue] };
DoFreeTree:
PROC [root: RefBranchNode] = {
itemClassID: ItemClassID ← 0;
itemClass: TiogaItemClass.ItemClass ← FetchItemClass[itemClassID];
basicClassID: BasicClassID ← 0;
basicClass: TiogaBasicClass.BasicClass ← FetchBasicClass[basicClassID];
DestroyItem:
PROC [item: RefItemNode] =
INLINE {
IF item.class # itemClassID
THEN
itemClass ← FetchItemClass[itemClassID ← item.class];
IF itemClass.destroy # NIL THEN itemClass.destroy[item] };
DestroyBasic:
PROC [basic: RefBasicNode] =
INLINE {
IF basic.class # basicClassID
THEN
basicClass ← FetchBasicClass[basicClassID ← basic.class];
IF basicClass.destroy # NIL THEN basicClass.destroy[basic] };
next, node: Ref;
IF root.child = NIL THEN RETURN; -- has already been freed
TRUSTED {Process.SetPriority[Process.priorityBackground]}; -- no rush to finish this
Process.Yield[];
[] ← TiogaLocks.Lock[root, "DoFreeTree", write]; -- must make sure no one still reading it. never unlock it.
node ← root; next ← NIL;
DO
-- go through the tree zapping REF's
WITH node
SELECT
FROM
br: RefBranchNode =>
IF br.contents # NIL THEN { next ← br.contents; br.contents ← NIL }
ELSE { next ← br.child; br.child ← NIL };
bx: RefBoxNode => next ← bx.contents;
ls: RefListNode => next ← ls.contents;
ENDCASE;
IF next # NIL THEN { node ← next; next ← NIL; LOOP };
next ← node.next; node.next ← NIL; node.last ← node.deleted ← TRUE;
The node has now been removed from the tree and its contents have been destroyed.
WITH node
SELECT
FROM
tx: RefTextNode => { DestroyItem[tx]; tx.rope ← NIL; tx.runs ← NIL };
bx: RefBoxNode => { DestroyItem[bx]; bx.data ← NIL };
ls: RefListNode => { DestroyItem[ls]; ls.data ← NIL };
bc: RefBasicNode => { DestroyBasic[bc]; bc.data ← NIL };
ENDCASE;
IF node.hasPropList THEN NodeProps.RemProps[node];
nodesFreed ← nodesFreed+1;
IF (node ← next) = NIL THEN EXIT;
ENDLOOP };