Geant4-11
G4FastList.icc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr)
28//
29// History:
30// -----------
31// 10 Oct 2011 M.Karamitros created
32//
33// -------------------------------------------------------------------
34
35//#ifndef G4FASTLIST_ICC_
36//#define G4FASTLIST_ICC_
37
38//***********************************************************
39// TrackList_iterator
40template<class OBJECT>
41 OBJECT*
42 G4FastList_iterator<OBJECT>::operator*()
43 {
44 if (fpNode == 0) return 0;
45 return fpNode->GetObject();
46 }
47
48template<class OBJECT>
49 OBJECT*
50 G4FastList_iterator<OBJECT>::operator->()
51 {
52 if (fpNode == 0) return 0;
53 return fpNode->GetObject();
54 }
55
56template<class OBJECT>
57 const OBJECT*
58 G4FastList_iterator<OBJECT>::operator*() const
59 {
60 if (fpNode == 0) return 0;
61 return fpNode->GetObject();
62 }
63
64template<class OBJECT>
65 const OBJECT*
66 G4FastList_iterator<OBJECT>::operator->() const
67 {
68 if (fpNode == 0) return 0;
69 return fpNode->GetObject();
70 }
71
72//***********************************************************
73// TrackNodeList
74
75template<class OBJECT>
76 G4FastListNode<OBJECT>::G4FastListNode(OBJECT* track) :
77 fpObject(track), fpPrevious(0), fpNext(0)
78 {
79 fAttachedToList = false;
80 }
81
82template<class OBJECT>
83 G4FastListNode<OBJECT>::~G4FastListNode()
84 {
85 if (fListRef && fListRef->fpList)
86 {
87 fListRef->fpList->pop(this);
88 }
89 }
90
91template<class OBJECT>
92 void G4FastListNode<OBJECT>::DetachYourSelf()
93 {
94 if(fpObject)
95 {
96 fpObject->SetListNode(0);
97 }
98 }
99
100//***********************************************************
101
102template<class OBJECT>
103 G4FastList<OBJECT>::G4FastList() :
104 fBoundary()
105 {
106 fListRef.reset(new _ListRef<G4FastList<OBJECT> >(this));
107 fNbObjects = 0;
108 fBoundary.SetPrevious(&fBoundary);
109 fBoundary.SetNext(&fBoundary);
110 fBoundary.fAttachedToList = true;
111 fpNodeInManyLists = 0;
112 }
113
114// should not be used
115template<class OBJECT>
116 G4FastList<OBJECT>::G4FastList(const G4FastList<OBJECT>& /*other*/) :
117 fBoundary()
118 {
119 // One track should not belong to two different trackLists
120 fNbObjects = 0;
121 fpNodeInManyLists = 0;
122 }
123
124template<class OBJECT>
125 G4FastList<OBJECT>& G4FastList<OBJECT>::operator=(const G4FastList<OBJECT>& other)
126 {
127 // One track should not belong to two different trackList
128 if (this == &other) return *this; // handle self assignment
129 //assignment operator
130 return *this;
131 }
132
133template<class OBJECT>
134 G4FastList<OBJECT>::~G4FastList()
135 {
136 if (fNbObjects != 0)
137 {
138 G4FastListNode<OBJECT> * __stackedTrack = fBoundary.GetNext();
139 G4FastListNode<OBJECT> * __nextStackedTrack;
140
141 // delete tracks in the stack
142 while (__stackedTrack && __stackedTrack != &(fBoundary))
143 {
144 __nextStackedTrack = __stackedTrack->GetNext();
145 OBJECT* __obj = __stackedTrack->GetObject();
146
147 delete __stackedTrack;
148 __stackedTrack = 0;
149
150 if (__obj)
151 {
152 //////////////
153 DeleteObject(__obj);
154 __obj = 0;
155 //////////////
156 }
157 __stackedTrack = __nextStackedTrack;
158 }
159 }
160 fNbObjects = 0;
161
162 typename WatcherSet::iterator it = fWatchers.begin();
163 typename WatcherSet::iterator _end = fWatchers.end();
164
165 for (; it != _end; it++)
166 {
167 (*it)->NotifyDeletingList(this);
168 (*it)->StopWatching(this, false);
169 }
170
171 if (fpNodeInManyLists)
172 {
173 delete fpNodeInManyLists;
174 fpNodeInManyLists = 0;
175 }
176 }
177
178template<class OBJECT>
179 bool G4FastList<OBJECT>::empty() const
180 {
181 return (fNbObjects == 0);
182 }
183
184template<class OBJECT>
185 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::begin()
186 {
187 return iterator(fBoundary.GetNext());
188 }
189
190template<class OBJECT>
191 typename G4FastList<OBJECT>::const_iterator G4FastList<OBJECT>::begin() const
192 {
193 return const_iterator(fBoundary.GetNext());
194 }
195
196template<class OBJECT>
197 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::end()
198 {
199 return iterator(&(fBoundary));
200 }
201
202template<class OBJECT>
203 typename G4FastList<OBJECT>::const_iterator G4FastList<OBJECT>::end() const
204 {
205 return const_iterator(&(fBoundary));
206 }
207// return an iterator that contains an empty node
208// use for boundary checking only
209
210template<class OBJECT>
211 void G4FastList<OBJECT>::push_front(OBJECT* __obj)
212 {
213 insert(begin(), __obj);
214 }
215
216template<class OBJECT>
217 void G4FastList<OBJECT>::push_back(OBJECT* __obj)
218 {
219 insert(end(), __obj);
220 }
221
222template<class OBJECT>
223 bool G4FastList<OBJECT>::Holds(const OBJECT* __obj) const
224 {
225 node* __node = GetNode(__obj);
226 if(__node == 0) return false;
227 return (__node->fListRef->fpList == this);
228 }
229
230// TODO: A revoir
231template<class OBJECT>
232 G4FastListNode<OBJECT>* G4FastList<OBJECT>::Flag(OBJECT* __obj)
233 {
234 G4FastListNode<OBJECT>* __node = GetNode(__obj);
235
236 if (__node != 0)
237 {
238 // Suggestion move the node to this list
239 if (__node->fAttachedToList)
240 {
241 G4ExceptionDescription exceptionDescription;
242 exceptionDescription << "An object";
243 exceptionDescription << " is already attached to a TrackList ";
244 G4Exception("G4FastList<OBJECT>::Flag", "G4FastList001",
245 FatalErrorInArgument, exceptionDescription);
246 }
247 }
248 else
249 {
250 __node = new G4FastListNode<OBJECT>(__obj);
251 SetNode(__obj,__node);
252 }
253
254 __node->fAttachedToList = true;
255 __node->fListRef = fListRef;
256 return __node;
257 }
258
259template<class OBJECT>
260 G4FastListNode<OBJECT>* G4FastList<OBJECT>::CreateNode(OBJECT* __obj)
261 {
262 G4FastListNode<OBJECT>* __listNode = Flag(__obj);
263 return __listNode;
264 }
265
266template<class OBJECT>
267 void G4FastList<OBJECT>::Hook(G4FastListNode<OBJECT>* __position,
268 G4FastListNode<OBJECT>* __toHook)
269 {
270 /*
271 __toHook->SetNext(__position);
272 __toHook->SetPrevious(__position->GetPrevious());
273 __position->GetPrevious()->SetNext(__toHook);
274 __position->SetPrevious(__toHook);
275 */
276 G4FastListNode<OBJECT>* __previous = __position->GetPrevious();
277 __toHook->SetPrevious(__previous);
278 __toHook->SetNext(__position);
279 __position->SetPrevious(__toHook);
280 __previous->SetNext(__toHook);
281
282 /*
283 if (fNbObjects == 0)
284 {
285 // DEBUG
286 // G4cout << "fNbObjects == 0" << G4endl;
287 fpStart = __toHook;
288 fpFinish = __toHook;
289 __toHook->SetNext(&fBoundary);
290 __toHook->SetPrevious(&fBoundary);
291 //fBoundary.SetNext(__toHook);
292 fBoundary.SetPrevious(__toHook);
293 } else if (__position == &fBoundary)
294 {
295 // DEBUG
296 // G4cout << "__position == &fBoundary" << G4endl;
297 fpFinish->SetNext(__toHook);
298 __toHook->SetPrevious(fpFinish);
299
300 __toHook->SetNext(&fBoundary);
301 fBoundary.SetPrevious(__toHook);
302
303 fpFinish = __toHook;
304 } else if (__position == fpStart)
305 {
306 // DEBUG
307 // G4cout << "__position == fStart" << G4endl;
308 __toHook->SetPrevious(&fBoundary);
309 //fBoundary.SetNext(__toHook);
310 __toHook->SetNext(fpStart);
311 fpStart->SetPrevious(__toHook);
312 fpStart = __toHook;
313 } else
314 {
315 // DEBUG
316 // G4cout << "else" << G4endl;
317 G4FastListNode<OBJECT>* __previous = __position->GetPrevious();
318 __toHook->SetPrevious(__previous);
319 __toHook->SetNext(__position);
320 __position->SetPrevious(__toHook);
321 __previous->SetNext(__toHook);
322 }
323 */
324 fNbObjects++;
325
326 if(fWatchers.empty() == false)
327 {
328 typename WatcherSet::iterator it = fWatchers.begin();
329 typename WatcherSet::iterator _end = fWatchers.end();
330
331 for (; it != _end; it++)
332 {
333 (*it)->NotifyAddObject(__toHook->GetObject(), this);
334 }
335 }
336 }
337
338template<class OBJECT>
339 void G4FastListNode<OBJECT>::UnHook()
340 {
341 G4FastListNode<OBJECT>* __next_node = this->fpNext;
342 G4FastListNode<OBJECT>* __prev_node = this->fpPrevious;
343
344 if (__prev_node)
345 {
346 __prev_node->fpNext = __next_node;
347 }
348
349 if (__next_node)
350 {
351 __next_node->fpPrevious = __prev_node;
352 }
353 fpNext = 0;
354 fpPrevious = 0;
355 }
356
357template<class OBJECT>
358 void G4FastList<OBJECT>::Unhook(G4FastListNode<OBJECT>* __toUnHook)
359 {
360 __toUnHook->UnHook();
361
362 fNbObjects--;
363
364 typename WatcherSet::iterator it = fWatchers.begin();
365 typename WatcherSet::iterator _end = fWatchers.end();
366
367 for (; it != _end; it++)
368 {
369 (*it)->NotifyRemoveObject(__toUnHook->GetObject(), this);
370 }
371 }
372
373template<class OBJECT>
374 typename G4FastList<OBJECT>::iterator
375 G4FastList<OBJECT>::insert(typename G4FastList<OBJECT>::iterator __position,
376 OBJECT* __obj)
377 {
378 G4FastListNode<OBJECT>* __node = CreateNode(__obj);
379 Hook(__position.fpNode, __node);
380 return iterator(__node);
381 }
382
383//____________________________________________________________________
384//
385// WITHDRAW FROM LIST
386//____________________________________________________________________
387
388template<class OBJECT>
389 void G4FastList<OBJECT>::CheckFlag(G4FastListNode<OBJECT>* __node)
390 {
391 if (__node->fListRef->fpList != this)
392 {
393 G4ExceptionDescription exceptionDescription;
394 exceptionDescription << "The object "
395 << " is not correctly linked to a G4FastList." << G4endl
396 << "You are probably trying to withdraw this object "
397 << "from the list but it probably does not belong to "
398 << "this fast list." << G4endl;
399 G4Exception("G4FastList<OBJECT>::CheckFlag", "G4FastList002",
400 FatalErrorInArgument, exceptionDescription);
401 }
402 }
403
404template<class OBJECT>
405 G4FastListNode<OBJECT>* G4FastList<OBJECT>::Unflag(OBJECT* __obj)
406 {
407 G4FastListNode<OBJECT>* __node = __GetNode(__obj);
408 CheckFlag(__node);
409 __node->fAttachedToList = false;
410 __node->fListRef.reset();
411 return __node;
412 }
413
414template<class OBJECT>
415 void G4FastList<OBJECT>::Unflag(G4FastListNode<OBJECT>* __node)
416 {
417 CheckFlag(__node);
418 __node->fAttachedToList = false;
419 __node->fListRef.reset();
420 return;
421 }
422
423template<class OBJECT>
424 OBJECT* G4FastList<OBJECT>::pop_back()
425 {
426 if (fNbObjects == 0) return 0;
427 G4FastListNode<OBJECT> * __aNode = fBoundary.GetPrevious();
428 Unhook(__aNode);
429 Unflag(__aNode);
430 return __aNode->GetObject();
431 }
432
433template<class OBJECT>
434 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::pop(OBJECT* __obj)
435 {
436 G4FastListNode<OBJECT>* __node = Unflag(__obj);
437 iterator __next(__node->GetNext());
438 Unhook(__node);
439 return __next;
440 }
441
442template<class OBJECT>
443 typename G4FastList<OBJECT>::iterator
444 G4FastList<OBJECT>::pop(G4FastListNode<OBJECT>* __node)
445 {
446 Unflag(__node);
447 iterator __next(__node->GetNext());
448 Unhook(__node);
449 return __next;
450 }
451
452template<class OBJECT>
453 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::erase(OBJECT* __obj)
454 {
455 G4FastListNode<OBJECT>* __next_node = EraseListNode(__obj);
456 //////////////////
457 DeleteObject(__obj);
458 __obj = 0;
459 //////////////////
460 iterator __next(__next_node);
461 return __next;
462 }
463
464template<class OBJECT>
465 G4FastListNode<OBJECT>* G4FastList<OBJECT>::EraseListNode(OBJECT* __obj)
466 {
467 G4FastListNode<OBJECT>* __node = Unflag(__obj);
468 __node->DetachYourSelf();
469 G4FastListNode<OBJECT>* __next = __node->GetNext();
470 Unhook(__node);
471 delete __node;
472 return __next;
473 }
474
475template<class OBJECT>
476 void G4FastList<OBJECT>::DeleteObject(OBJECT*)
477 {
478// delete __obj;
479 }
480
481template<class OBJECT>
482 void G4FastList<OBJECT>::remove(OBJECT* __obj)
483 {
484 this->erase(__obj);
485 }
486
487template<class OBJECT>
488 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::pop(iterator __first,
489 iterator __last)
490 {
491 if (fNbObjects == 0) return iterator(&fBoundary);
492
493 while (__first != __last)
494 {
495 if (__first.fpNode) __first = pop(*__first);
496 }
497 return __last;
498 }
499
500template<class OBJECT>
501 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::erase(iterator __first,
502 iterator __last)
503 {
504 if (fNbObjects == 0) return iterator(&fBoundary);
505
506 while (__first != __last)
507 {
508 if (__first.fpNode) __first = erase(*__first);
509 }
510 return __last;
511 }
512
513template<class OBJECT>
514 void G4FastList<OBJECT>::clear()
515 {
516 erase(begin(), end());
517 }
518
519template<class OBJECT>
520 void G4FastList<OBJECT>::transferTo(G4FastList<OBJECT>* __destination)
521 {
522 if (fNbObjects == 0) return;
523
524 if (__destination->fNbObjects == 0)
525 {
526
527 if(__destination->fWatchers.empty()==false)
528 {
529 typename WatcherSet::iterator it = __destination->fWatchers.begin();
530 typename WatcherSet::iterator _end = __destination->fWatchers.end();
531
532// G4cout << "G4FastList<OBJECT>::transferTo --- Watcher size = "
533// << __destination->fWatchers.size()
534// << G4endl;
535
536 for (; it != _end; it++)
537 {
538 for(iterator it2 = this->begin() ;
539 it2 != this->end(); ++it2
540 )
541 {
542 (*it)->NotifyAddObject(*it2, this);
543 }
544 }
545 }
546
547 __destination->fNbObjects = this->fNbObjects;
548
549 __destination->fBoundary.SetNext(fBoundary.GetNext());
550 __destination->fBoundary.SetPrevious(fBoundary.GetPrevious());
551 fBoundary.GetNext()->SetPrevious(&__destination->fBoundary);
552 fBoundary.GetPrevious()->SetNext(&__destination->fBoundary);
553 }
554 else
555 {
556 if(__destination->fWatchers.empty()==false)
557 {
558 typename WatcherSet::iterator it = __destination->fWatchers.begin();
559 typename WatcherSet::iterator _end = __destination->fWatchers.end();
560
561 for (; it != _end; it++)
562 {
563 for(iterator it2 = this->begin() ;
564 it2 != this->end(); ++it2)
565 {
566 (*it)->NotifyAddObject(*it2, this);
567 }
568 }
569 }
570
571 node* lastNode = __destination->fBoundary.GetPrevious();
572 lastNode->SetNext(fBoundary.GetNext());
573 fBoundary.GetNext()->SetPrevious(lastNode);
574 __destination->fBoundary.SetPrevious(fBoundary.GetPrevious());
575 fBoundary.GetPrevious()->SetNext(&__destination->fBoundary);
576
577 __destination->fNbObjects += this->fNbObjects;
578 }
579
580 fNbObjects = 0;
581 this->fBoundary.SetPrevious(&this->fBoundary);
582 this->fBoundary.SetNext(&this->fBoundary);
583
584 fListRef->fpList = __destination;
585 }
586
587//____________________________________________________________
588//
589// G4FastList<OBJECT> Utils
590//____________________________________________________________
591
592template<class OBJECT>
593 G4FastListNode<OBJECT>* G4FastList<OBJECT>::__GetNode(OBJECT* __obj)
594 {
595 G4FastListNode<OBJECT>* __node = GetNode(__obj);
596 // TODO : complete the exception
597 if (__node == 0)
598 {
599 G4ExceptionDescription exceptionDescription;
600 exceptionDescription << "The object ";
601 exceptionDescription << " was not connected to any trackList ";
602 G4Exception("G4FastList<OBJECT>::Unflag", "G4FastList003",
603 FatalErrorInArgument, exceptionDescription);
604 return 0;
605 }
606 return __node;
607 }
608
609template<class OBJECT>
610 G4FastListNode<OBJECT>* G4FastList<OBJECT>::GetNode(OBJECT* __obj)
611 {
612 G4FastListNode<OBJECT>* __node = __obj->GetListNode();
613 return __node;
614 }
615
616template<class OBJECT>
617 void G4FastList<OBJECT>::SetNode(OBJECT* __obj,
618 G4FastListNode<OBJECT>* __node)
619 {
620 __obj->SetListNode(__node);
621 }
622
623template<class OBJECT>
624 G4FastList<OBJECT>* G4FastList<OBJECT>::GetList(OBJECT* __obj)
625 {
626 G4FastListNode<OBJECT>* __node = GetNode(__obj);
627
628 if (__node == 0) return 0;
629 if (__node->fListRef == nullptr) return 0;
630
631 return __node->fListRef->fpTrackList;
632 }
633
634template<class OBJECT>
635 G4FastList<OBJECT>*
636 G4FastList<OBJECT>::GetList(G4FastListNode<OBJECT>* __node)
637 {
638 if (__node == 0) return 0;
639 if (__node->fListRef == nullptr) return 0;
640
641 return __node->fListRef->fpList;
642 }
643
644template<class OBJECT>
645 void G4FastList<OBJECT>::Pop(OBJECT* __obj)
646 {
647 G4FastListNode<OBJECT>* __node = G4FastList<OBJECT>::GetNode(__obj);
648 G4FastList<OBJECT>* __list = G4FastList<OBJECT>::GetList(__node);
649 if (__list) __list->pop(__node);
650 }
651
652//#endif /* G4FASTLIST_ICC_*/