initial working frustum culling implementation
[chaz/yoink] / src / Moof / stlplus / safe_iterator.tpp
1 namespace stlplus
2 {
3
4 ////////////////////////////////////////////////////////////////////////////////
5 // body class implements the aliasing behaviour
6
7 template<typename O, typename N>
8 class safe_iterator_body
9 {
10 private:
11 const O* m_owner;
12 N* m_node;
13 unsigned m_count;
14
15 public:
16
17 safe_iterator_body(const O* owner, N* node) throw() :
18 m_owner(owner), m_node(node), m_count(1)
19 {
20 // std::cerr << "constructing "
21 // << std::hex << ((unsigned long)this)
22 // << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node)
23 // << ":" << std::dec << m_count << std::endl;
24 }
25
26 ~safe_iterator_body(void) throw()
27 {
28 // std::cerr << "destroying "
29 // << std::hex << ((unsigned long)this)
30 // << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node)
31 // << ":" << std::dec << m_count << std::endl;
32 m_owner = 0;
33 m_node = 0;
34 }
35
36 unsigned count(void) const
37 {
38 return m_count;
39 }
40
41 void increment(void)
42 {
43 ++m_count;
44 // std::cerr << "incremented "
45 // << std::hex << ((unsigned long)this)
46 // << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node)
47 // << ":" << std::dec << m_count << std::endl;
48 }
49
50 bool decrement(void)
51 {
52 --m_count;
53 // std::cerr << "decremented "
54 // << std::hex << ((unsigned long)this)
55 // << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node)
56 // << ":" << std::dec << m_count << std::endl;
57 return m_count == 0;
58 }
59
60 N* node(void) const throw()
61 {
62 return m_node;
63 }
64
65 const O* owner(void) const throw()
66 {
67 return m_owner;
68 }
69
70 void change_owner(const O* owner)
71 {
72 m_owner = owner;
73 }
74
75 bool equal(const safe_iterator_body<O,N>* right) const throw()
76 {
77 // return m_node == right->m_node;
78 return compare(right) == 0;
79 }
80
81 int compare(const safe_iterator_body<O,N>* right) const throw()
82 {
83 return ((long)m_node) - ((long)right->m_node);
84 }
85
86 bool null(void) const throw()
87 {
88 return m_owner == 0;
89 }
90
91 bool end(void) const throw()
92 {
93 return m_owner != 0 && m_node == 0;
94 }
95
96 bool valid(void) const throw()
97 {
98 return m_owner != 0 && m_node != 0;
99 }
100
101 void set_end(void) throw()
102 {
103 m_node = 0;
104 }
105
106 void set_null(void) throw()
107 {
108 m_owner = 0;
109 m_node = 0;
110 }
111
112 void assert_valid(void) const throw(null_dereference,end_dereference)
113 {
114 if (null())
115 throw null_dereference("stlplus::safe_iterator");
116 if (end())
117 throw end_dereference("stlplus::safe_iterator");
118 }
119
120 void assert_non_null(void) const throw(null_dereference)
121 {
122 if (null())
123 throw null_dereference("stlplus::safe_iterator");
124 }
125
126 void assert_owner(const O* owner) const throw(wrong_object)
127 {
128 if (owner != m_owner)
129 throw wrong_object("stlplus::safe_iterator");
130 }
131 };
132
133
134 ////////////////////////////////////////////////////////////////////////////////
135 // Master Iterator
136 ////////////////////////////////////////////////////////////////////////////////
137
138 // construct a valid iterator
139 template<typename O, typename N>
140 master_iterator<O,N>::master_iterator(const O* owner, N* node) throw() :
141 m_body(new safe_iterator_body<O,N>(owner,node))
142 {
143 }
144
145 // destructor - disconnect all iterators from the node
146 // this usually happens when the node is deleted and must invalidate all aliases
147 template<typename O, typename N>
148 master_iterator<O,N>::~master_iterator(void) throw()
149 {
150 m_body->set_end();
151 if(m_body->decrement())
152 {
153 delete m_body;
154 m_body = 0;
155 }
156 }
157
158 // dereference
159 template<typename O, typename N>
160 N* master_iterator<O,N>::node(void) const throw()
161 {
162 return m_body->node();
163 }
164
165 template<typename O, typename N>
166 const O* master_iterator<O,N>::owner(void) const throw()
167 {
168 return m_body->owner();
169 }
170
171 // when you move a node from one owner to another, call this on the node's iterator
172 // this effectively moves all iterators to the node so that they are owned by the new owner too
173 template<typename O, typename N>
174 void master_iterator<O,N>::change_owner(const O* owner) throw()
175 {
176 m_body->change_owner(owner);
177 }
178
179 ////////////////////////////////////////////////////////////////////////////////
180 // Safe Iterator
181 ////////////////////////////////////////////////////////////////////////////////
182
183 // construct a null iterator
184 // later assignment of a valid iterator to this is done by using step
185 template<typename O, typename N>
186 safe_iterator<O,N>::safe_iterator(void) throw() :
187 m_body(new safe_iterator_body<O,N>(0,0))
188 {
189 }
190
191 // construct a valid iterator by aliasing from the owner node's master iterator
192 template<typename O, typename N>
193 safe_iterator<O,N>::safe_iterator(const master_iterator<O,N>& r) throw() :
194 m_body(0)
195 {
196 m_body = r.m_body;
197 m_body->increment();
198 }
199
200 // construct a valid iterator by aliasing from the owner node's master iterator
201 template<typename O, typename N>
202 safe_iterator<O,N>::safe_iterator(const safe_iterator<O,N>& r) throw() :
203 m_body(0)
204 {
205 m_body = r.m_body;
206 m_body->increment();
207 }
208
209 // assignment implements dealiasing followed by aliasing
210 template<typename O, typename N>
211 safe_iterator<O,N>& safe_iterator<O,N>::operator=(const safe_iterator<O,N>& r) throw()
212 {
213 if (m_body != r.m_body)
214 {
215 if (m_body->decrement())
216 delete m_body;
217 m_body = r.m_body;
218 m_body->increment();
219 }
220 return *this;
221 }
222
223 // destructor - implements dealiasing
224 template<typename O, typename N>
225 safe_iterator<O,N>::~safe_iterator(void) throw()
226 {
227 if(m_body->decrement())
228 {
229 delete m_body;
230 m_body = 0;
231 }
232 }
233
234
235 // increment/decrement operation
236 // implements dealiasing followed by aliasing
237 template<typename O, typename N>
238 void safe_iterator<O,N>::set(const master_iterator<O,N>& r) throw()
239 {
240 if (m_body != r.m_body)
241 {
242 if (m_body->decrement())
243 delete m_body;
244 m_body = r.m_body;
245 m_body->increment();
246 }
247 }
248
249 // dereference
250 template<typename O, typename N>
251 N* safe_iterator<O,N>::node(void) const throw()
252 {
253 return m_body->node();
254 }
255
256 template<typename O, typename N>
257 const O* safe_iterator<O,N>::owner(void) const throw()
258 {
259 return m_body->owner();
260 }
261
262 // change to a null iterator - i.e. one that doees not belong to any object
263 // this does not affect any other iterators pointing to the same node
264 template<typename O, typename N>
265 void safe_iterator<O,N>::set_null(void) throw()
266 {
267 if (m_body->count() == 1)
268 {
269 // no aliases, so just make this null
270 m_body->set_null();
271 }
272 else
273 {
274 // create a new body which is null so as not to affect any other aliases
275 m_body->decrement();
276 m_body = new safe_iterator_body<O,N>(0,0);
277 }
278 }
279
280 ////////////////////////////////////////////////////////////////////////////////
281 // operations for clients that do not have a master end iterator
282 // alternatively, have a master end iterator as part of the container
283 // and call constructor(master_end) or step(master_end)
284
285 // construct an end iterator
286 template<typename O, typename N>
287 safe_iterator<O,N>::safe_iterator(const O* owner) throw() :
288 m_body(new safe_iterator_body<O,N>(owner,0))
289 {
290 }
291
292 // change to an end iterator - e.g. as a result of incrementing off the end
293 template<typename O, typename N>
294 void safe_iterator<O,N>::set_end(void) throw()
295 {
296 if (m_body->count() == 1)
297 {
298 // no aliases, so just make this an end iterator
299 m_body->set_end();
300 }
301 else
302 {
303 // create a new body which is null so as not to affect any other aliases
304 m_body->decrement();
305 m_body = new safe_iterator_body<O,N>(owner(),0);
306 }
307 }
308
309 ////////////////////////////////////////////////////////////////////////////////
310 // tests
311
312 // comparison
313 template<typename O, typename N>
314 bool safe_iterator<O,N>::equal(const safe_iterator<O,N>& right) const throw()
315 {
316 return compare(right) == 0;
317 }
318
319 template<typename O, typename N>
320 int safe_iterator<O,N>::compare(const safe_iterator<O,N>& right) const throw()
321 {
322 if (m_body == right.m_body) return 0;
323 return m_body->compare(right.m_body);
324 }
325
326 // a null iterator is one that has not been initialised with a value yet
327 template<typename O, typename N>
328 bool safe_iterator<O,N>::null(void) const throw()
329 {
330 return m_body->null();
331 }
332
333 // an end iterator is one that points to the end element of the list of nodes
334 template<typename O, typename N>
335 bool safe_iterator<O,N>::end(void) const throw()
336 {
337 return m_body->end();
338 }
339
340 // a valid iterator is one that can be dereferenced
341 template<typename O, typename N>
342 bool safe_iterator<O,N>::valid(void) const throw()
343 {
344 return m_body->valid();
345 }
346
347 // check the rules for a valid iterator that can be dereferenced
348 template<typename O, typename N>
349 void safe_iterator<O,N>::assert_valid(void) const throw(null_dereference,end_dereference)
350 {
351 m_body->assert_valid();
352 }
353
354 template<typename O, typename N>
355 void safe_iterator<O,N>::assert_valid(const O* owner) const throw(wrong_object,null_dereference,end_dereference)
356 {
357 m_body->assert_valid();
358 m_body->assert_owner(owner);
359 }
360
361 template<typename O, typename N>
362 void safe_iterator<O,N>::assert_non_null(void) const throw(null_dereference)
363 {
364 m_body->assert_non_null();
365 }
366
367 template<typename O, typename N>
368 void safe_iterator<O,N>::assert_owner(const O* owner) const throw(wrong_object)
369 {
370 m_body->assert_owner(owner);
371 }
372
373 } // end namespace stlplus
This page took 0.051498 seconds and 5 git commands to generate.