]>
Commit | Line | Data |
---|---|---|
8e08b761 | 1 | ///////////////////////////////////////////////////////////////////////////// |
4cbc57f0 JS |
2 | // Name: garbagec.cpp |
3 | // Purpose: Garbage collection algorithm for optimizing refresh. | |
8e08b761 JS |
4 | // Author: Aleksandras Gluchovas |
5 | // Modified by: | |
6 | // Created: 18/10/98 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) Aleksandras Gluchovas | |
4cbc57f0 | 9 | // Licence: wxWindows licence |
8e08b761 JS |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
12 | ||
13 | #ifdef __GNUG__ | |
14 | #pragma implementation "garbagec.h" | |
15 | #endif | |
16 | ||
17 | // For compilers that support precompilation, includes "wx/wx.h". | |
18 | #include "wx/wxprec.h" | |
19 | ||
20 | #ifdef __BORLANDC__ | |
21 | #pragma hdrstop | |
22 | #endif | |
23 | ||
24 | ||
25 | #ifndef WX_PRECOMP | |
26 | #include "wx/wx.h" | |
27 | #endif | |
28 | ||
29 | #include "wx/fl/garbagec.h" | |
30 | ||
31 | /***** Implementation for class GarbageCollector *****/ | |
32 | ||
33 | inline static GCItem& node_to_item( wxNode* pNode ) | |
34 | { | |
8495ba53 | 35 | return *( (GCItem*)(pNode->GetData()) ); |
8e08b761 JS |
36 | } |
37 | ||
38 | GarbageCollector::~GarbageCollector() | |
39 | { | |
4cbc57f0 | 40 | Reset(); |
8e08b761 JS |
41 | } |
42 | ||
43 | /*** GC alg. helpers ***/ | |
44 | ||
45 | void GarbageCollector::DestroyItemList( wxList& lst ) | |
46 | { | |
8495ba53 | 47 | wxNode* pNode = lst.GetFirst(); |
8e08b761 | 48 | |
4cbc57f0 JS |
49 | while( pNode ) |
50 | { | |
51 | delete &node_to_item( pNode ); | |
8e08b761 | 52 | |
8495ba53 | 53 | pNode = pNode->GetNext(); |
4cbc57f0 | 54 | } |
8e08b761 | 55 | |
4cbc57f0 | 56 | lst.Clear(); |
8e08b761 JS |
57 | } |
58 | ||
59 | wxNode* GarbageCollector::FindItemNode( void* pForObj ) | |
60 | { | |
8495ba53 | 61 | wxNode* pNode = mAllNodes.GetFirst(); |
8e08b761 | 62 | |
4cbc57f0 JS |
63 | while( pNode ) |
64 | { | |
65 | if ( node_to_item( pNode ).mpObj == pForObj ) | |
8e08b761 | 66 | |
4cbc57f0 | 67 | return pNode; |
8e08b761 | 68 | |
8495ba53 | 69 | pNode = pNode->GetNext(); |
4cbc57f0 | 70 | } |
8e08b761 | 71 | |
8552e6f0 | 72 | return NULL; |
8e08b761 JS |
73 | } |
74 | ||
75 | wxNode* GarbageCollector::FindReferenceFreeItemNode() | |
76 | { | |
8495ba53 | 77 | wxNode* pNode = mAllNodes.GetFirst(); |
8e08b761 | 78 | |
4cbc57f0 JS |
79 | while( pNode ) |
80 | { | |
8495ba53 | 81 | if ( node_to_item( pNode ).mRefs.GetCount() == 0 ) |
8e08b761 | 82 | |
4cbc57f0 | 83 | return pNode; |
8e08b761 | 84 | |
8495ba53 | 85 | pNode = pNode->GetNext(); |
4cbc57f0 | 86 | } |
8e08b761 | 87 | |
4cbc57f0 | 88 | return 0; |
8e08b761 JS |
89 | } |
90 | ||
91 | void GarbageCollector::RemoveReferencesToNode( wxNode* pItemNode ) | |
92 | { | |
8495ba53 | 93 | wxNode* pNode = mAllNodes.GetFirst(); |
8e08b761 | 94 | |
4cbc57f0 JS |
95 | while( pNode ) |
96 | { | |
97 | wxList& refLst = node_to_item( pNode ).mRefs; | |
8495ba53 | 98 | wxNode* pRefNode = refLst.GetFirst(); |
8e08b761 | 99 | |
4cbc57f0 JS |
100 | while( pRefNode ) |
101 | { | |
8495ba53 | 102 | if ( pRefNode->GetData() == (wxObject*)pItemNode ) |
4cbc57f0 | 103 | { |
8495ba53 | 104 | wxNode* pNext = pRefNode->GetNext(); |
8e08b761 | 105 | |
4cbc57f0 | 106 | refLst.DeleteNode( pRefNode ); |
8e08b761 | 107 | |
4cbc57f0 | 108 | pRefNode = pNext; |
8e08b761 | 109 | |
4cbc57f0 JS |
110 | continue; |
111 | } | |
8495ba53 | 112 | else pRefNode = pRefNode->GetNext(); |
4cbc57f0 | 113 | } |
8e08b761 | 114 | |
8495ba53 | 115 | pNode = pNode->GetNext(); |
4cbc57f0 | 116 | } |
8e08b761 JS |
117 | } |
118 | ||
119 | void GarbageCollector::ResolveReferences() | |
120 | { | |
8495ba53 | 121 | wxNode* pNode = mAllNodes.GetFirst(); |
8e08b761 | 122 | |
4cbc57f0 JS |
123 | while( pNode ) |
124 | { | |
125 | GCItem& item = node_to_item( pNode ); | |
8e08b761 | 126 | |
8495ba53 | 127 | wxNode* pRefNode = item.mRefs.GetFirst(); |
8e08b761 | 128 | |
4cbc57f0 JS |
129 | while( pRefNode ) |
130 | { | |
8495ba53 | 131 | pRefNode->SetData( (wxObject*) FindItemNode( (void*)pRefNode->GetData() ) ); |
8e08b761 | 132 | |
8495ba53 | 133 | pRefNode = pRefNode->GetNext(); |
4cbc57f0 | 134 | } |
8e08b761 | 135 | |
8495ba53 | 136 | pNode = pNode->GetNext(); |
4cbc57f0 | 137 | } |
8e08b761 JS |
138 | } |
139 | ||
196be0f1 | 140 | void GarbageCollector::AddObject( void* pObj, int WXUNUSED(refCnt) ) |
8e08b761 | 141 | { |
4cbc57f0 | 142 | // FOR NOW:: initial ref-count is not used |
8e08b761 | 143 | |
4cbc57f0 | 144 | GCItem* pItem = new GCItem(); |
8e08b761 | 145 | |
4cbc57f0 | 146 | pItem->mpObj = pObj; |
8e08b761 | 147 | |
4cbc57f0 | 148 | mAllNodes.Append( (wxObject*) pItem ); |
8e08b761 JS |
149 | } |
150 | ||
151 | void GarbageCollector::AddDependency( void* pObj, void* pDependsOnObj ) | |
152 | { | |
4cbc57f0 | 153 | node_to_item( FindItemNode( pObj ) ).mRefs.Append( (wxObject*)pDependsOnObj ); |
8e08b761 JS |
154 | } |
155 | ||
156 | /*** GC alg. implementation ***/ | |
157 | ||
158 | void GarbageCollector::ArrangeCollection() | |
159 | { | |
4cbc57f0 | 160 | ResolveReferences(); |
8e08b761 | 161 | |
4cbc57f0 JS |
162 | do |
163 | { | |
164 | // find node, which does not depend on anything | |
8e08b761 | 165 | |
4cbc57f0 | 166 | wxNode* pItemNode = FindReferenceFreeItemNode(); |
8e08b761 | 167 | |
4cbc57f0 JS |
168 | if ( pItemNode ) |
169 | { | |
170 | // append it to the list, where items are contained | |
171 | // in the increasing order of dependencies | |
8e08b761 | 172 | |
8495ba53 | 173 | mRegularLst.Append( pItemNode->GetData() ); |
8e08b761 | 174 | |
4cbc57f0 | 175 | mAllNodes.DeleteNode( pItemNode ); |
8e08b761 | 176 | |
4cbc57f0 JS |
177 | // remove references to this current "least-dependent" node |
178 | // from reference lists of all the other nodes | |
8e08b761 | 179 | |
4cbc57f0 JS |
180 | RemoveReferencesToNode( pItemNode ); |
181 | } | |
182 | else | |
183 | { | |
184 | // otherwise, what is left - all nodes, which | |
185 | // are involved into cycled chains (rings) | |
8e08b761 | 186 | |
8495ba53 | 187 | wxNode* pNode = mAllNodes.GetFirst(); |
8e08b761 | 188 | |
4cbc57f0 JS |
189 | while( pNode ) |
190 | { | |
8495ba53 | 191 | mCycledLst.Append( pNode->GetData() ); |
8e08b761 | 192 | |
8495ba53 | 193 | pNode = pNode->GetNext(); |
4cbc57f0 | 194 | } |
8e08b761 | 195 | |
4926b15b | 196 | mAllNodes.Clear(); |
4cbc57f0 JS |
197 | break; |
198 | } | |
8e08b761 | 199 | |
4cbc57f0 | 200 | // continue search for "least-dependent" nodes |
8e08b761 | 201 | |
4cbc57f0 | 202 | } while(1); |
8e08b761 JS |
203 | } |
204 | ||
205 | wxList& GarbageCollector::GetRegularObjects() | |
206 | { | |
4cbc57f0 | 207 | return mRegularLst; |
8e08b761 JS |
208 | } |
209 | ||
210 | wxList& GarbageCollector::GetCycledObjects() | |
211 | { | |
4cbc57f0 | 212 | return mCycledLst; |
8e08b761 JS |
213 | } |
214 | ||
215 | void GarbageCollector::Reset() | |
216 | { | |
4cbc57f0 | 217 | DestroyItemList( mAllNodes ); |
4926b15b GT |
218 | DestroyItemList( mRegularLst ); |
219 | DestroyItemList( mCycledLst ); | |
8e08b761 JS |
220 | } |
221 |