2 // ********************************************************************
3 // * License and Disclaimer *
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. *
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. *
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 // ********************************************************************
26 // $Id: G4FastList.cc 85244 2014-10-27 08:24:13Z gcosmo $
28 // Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr)
32 // 10 Oct 2011 M.Karamitros created
34 // -------------------------------------------------------------------
36 //#ifndef G4FASTLIST_ICC_
37 //#define G4FASTLIST_ICC_
39 //***********************************************************
41 template<class OBJECT>
43 G4FastList_iterator<OBJECT>::operator*()
45 if (fpNode == 0) return 0;
46 return fpNode->GetObject();
49 template<class OBJECT>
51 G4FastList_iterator<OBJECT>::operator->()
53 if (fpNode == 0) return 0;
54 return fpNode->GetObject();
57 template<class OBJECT>
59 G4FastList_iterator<OBJECT>::operator*() const
61 if (fpNode == 0) return 0;
62 return fpNode->GetObject();
65 template<class OBJECT>
67 G4FastList_iterator<OBJECT>::operator->() const
69 if (fpNode == 0) return 0;
70 return fpNode->GetObject();
73 //***********************************************************
76 template<class OBJECT>
77 G4FastListNode<OBJECT>::G4FastListNode(OBJECT* track) :
78 fpObject(track), fpPrevious(0), fpNext(0)
80 fAttachedToList = false;
83 template<class OBJECT>
84 G4FastListNode<OBJECT>::~G4FastListNode()
86 if (fListRef && fListRef->fpList)
88 fListRef->fpList->pop(this);
92 template<class OBJECT>
93 void G4FastListNode<OBJECT>::DetachYourSelf()
97 fpObject->SetListNode(0);
101 //***********************************************************
103 template<class OBJECT>
104 G4FastList<OBJECT>::G4FastList() :
107 fListRef.reset(new _ListRef<G4FastList<OBJECT> >(this));
109 fBoundary.SetPrevious(&fBoundary);
110 fBoundary.SetNext(&fBoundary);
111 fBoundary.fAttachedToList = true;
112 fpNodeInManyLists = 0;
115 // should not be used
116 template<class OBJECT>
117 G4FastList<OBJECT>::G4FastList(const G4FastList<OBJECT>& /*other*/) :
120 // One track should not belong to two different trackLists
122 fpNodeInManyLists = 0;
125 template<class OBJECT>
126 G4FastList<OBJECT>& G4FastList<OBJECT>::operator=(const G4FastList<OBJECT>& other)
128 // One track should not belong to two different trackList
129 if (this == &other) return *this; // handle self assignment
130 //assignment operator
134 template<class OBJECT>
135 G4FastList<OBJECT>::~G4FastList()
139 G4FastListNode<OBJECT> * __stackedTrack = fBoundary.GetNext();
140 G4FastListNode<OBJECT> * __nextStackedTrack;
142 // delete tracks in the stack
143 while (__stackedTrack && __stackedTrack != &(fBoundary))
145 __nextStackedTrack = __stackedTrack->GetNext();
146 OBJECT* __obj = __stackedTrack->GetObject();
148 delete __stackedTrack;
158 __stackedTrack = __nextStackedTrack;
163 typename WatcherSet::iterator it = fWatchers.begin();
164 typename WatcherSet::iterator _end = fWatchers.end();
166 for (; it != _end; it++)
168 (*it)->NotifyDeletingList(this);
169 (*it)->StopWatching(this, false);
172 if (fpNodeInManyLists)
174 delete fpNodeInManyLists;
175 fpNodeInManyLists = 0;
179 template<class OBJECT>
180 bool G4FastList<OBJECT>::empty() const
182 return (fNbObjects == 0);
185 template<class OBJECT>
186 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::begin()
188 return iterator(fBoundary.GetNext());
191 template<class OBJECT>
192 typename G4FastList<OBJECT>::const_iterator G4FastList<OBJECT>::begin() const
194 return const_iterator(fBoundary.GetNext());
197 template<class OBJECT>
198 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::end()
200 return iterator(&(fBoundary));
203 template<class OBJECT>
204 typename G4FastList<OBJECT>::const_iterator G4FastList<OBJECT>::end() const
206 return const_iterator(&(fBoundary));
208 // return an iterator that contains an empty node
209 // use for boundary checking only
211 template<class OBJECT>
212 void G4FastList<OBJECT>::push_front(OBJECT* __obj)
214 insert(begin(), __obj);
217 template<class OBJECT>
218 void G4FastList<OBJECT>::push_back(OBJECT* __obj)
220 insert(end(), __obj);
223 template<class OBJECT>
224 bool G4FastList<OBJECT>::Holds(const OBJECT* __obj) const
226 node* __node = GetNode(__obj);
227 if(__node == 0) return false;
228 return (__node->fListRef->fpList == this);
232 template<class OBJECT>
233 G4FastListNode<OBJECT>* G4FastList<OBJECT>::Flag(OBJECT* __obj)
235 G4FastListNode<OBJECT>* __node = GetNode(__obj);
239 // Suggestion move the node to this list
240 if (__node->fAttachedToList)
242 G4ExceptionDescription exceptionDescription;
243 exceptionDescription << "An object";
244 exceptionDescription << " is already attached to a TrackList ";
245 G4Exception("G4FastList<OBJECT>::Flag", "G4FastList001",
246 FatalErrorInArgument, exceptionDescription);
251 __node = new G4FastListNode<OBJECT>(__obj);
252 SetNode(__obj,__node);
255 __node->fAttachedToList = true;
256 __node->fListRef = fListRef;
260 template<class OBJECT>
261 G4FastListNode<OBJECT>* G4FastList<OBJECT>::CreateNode(OBJECT* __obj)
263 G4FastListNode<OBJECT>* __listNode = Flag(__obj);
267 template<class OBJECT>
268 void G4FastList<OBJECT>::Hook(G4FastListNode<OBJECT>* __position,
269 G4FastListNode<OBJECT>* __toHook)
272 __toHook->SetNext(__position);
273 __toHook->SetPrevious(__position->GetPrevious());
274 __position->GetPrevious()->SetNext(__toHook);
275 __position->SetPrevious(__toHook);
277 G4FastListNode<OBJECT>* __previous = __position->GetPrevious();
278 __toHook->SetPrevious(__previous);
279 __toHook->SetNext(__position);
280 __position->SetPrevious(__toHook);
281 __previous->SetNext(__toHook);
287 // G4cout << "fNbObjects == 0" << G4endl;
290 __toHook->SetNext(&fBoundary);
291 __toHook->SetPrevious(&fBoundary);
292 //fBoundary.SetNext(__toHook);
293 fBoundary.SetPrevious(__toHook);
294 } else if (__position == &fBoundary)
297 // G4cout << "__position == &fBoundary" << G4endl;
298 fpFinish->SetNext(__toHook);
299 __toHook->SetPrevious(fpFinish);
301 __toHook->SetNext(&fBoundary);
302 fBoundary.SetPrevious(__toHook);
305 } else if (__position == fpStart)
308 // G4cout << "__position == fStart" << G4endl;
309 __toHook->SetPrevious(&fBoundary);
310 //fBoundary.SetNext(__toHook);
311 __toHook->SetNext(fpStart);
312 fpStart->SetPrevious(__toHook);
317 // G4cout << "else" << G4endl;
318 G4FastListNode<OBJECT>* __previous = __position->GetPrevious();
319 __toHook->SetPrevious(__previous);
320 __toHook->SetNext(__position);
321 __position->SetPrevious(__toHook);
322 __previous->SetNext(__toHook);
327 if(fWatchers.empty() == false)
329 typename WatcherSet::iterator it = fWatchers.begin();
330 typename WatcherSet::iterator _end = fWatchers.end();
332 for (; it != _end; it++)
334 (*it)->NotifyAddObject(__toHook->GetObject(), this);
339 template<class OBJECT>
340 void G4FastListNode<OBJECT>::UnHook()
342 G4FastListNode<OBJECT>* __next_node = this->fpNext;
343 G4FastListNode<OBJECT>* __prev_node = this->fpPrevious;
347 __prev_node->fpNext = __next_node;
352 __next_node->fpPrevious = __prev_node;
358 template<class OBJECT>
359 void G4FastList<OBJECT>::Unhook(G4FastListNode<OBJECT>* __toUnHook)
361 __toUnHook->UnHook();
365 typename WatcherSet::iterator it = fWatchers.begin();
366 typename WatcherSet::iterator _end = fWatchers.end();
368 for (; it != _end; it++)
370 (*it)->NotifyRemoveObject(__toUnHook->GetObject(), this);
374 template<class OBJECT>
375 typename G4FastList<OBJECT>::iterator
376 G4FastList<OBJECT>::insert(typename G4FastList<OBJECT>::iterator __position,
379 G4FastListNode<OBJECT>* __node = CreateNode(__obj);
380 Hook(__position.fpNode, __node);
381 return iterator(__node);
384 //____________________________________________________________________
386 // WITHDRAW FROM LIST
387 //____________________________________________________________________
389 template<class OBJECT>
390 void G4FastList<OBJECT>::CheckFlag(G4FastListNode<OBJECT>* __node)
392 if (__node->fListRef->fpList != this)
394 G4ExceptionDescription exceptionDescription;
395 exceptionDescription << "The object "
396 << " is not correctly linked to a G4FastList." << G4endl
397 << "You are probably trying to withdraw this object "
398 << "from the list but it probably does not belong to "
399 << "this fast list." << G4endl;
400 G4Exception("G4FastList<OBJECT>::CheckFlag", "G4FastList002",
401 FatalErrorInArgument, exceptionDescription);
405 template<class OBJECT>
406 G4FastListNode<OBJECT>* G4FastList<OBJECT>::Unflag(OBJECT* __obj)
408 G4FastListNode<OBJECT>* __node = __GetNode(__obj);
410 __node->fAttachedToList = false;
411 __node->fListRef.reset();
415 template<class OBJECT>
416 void G4FastList<OBJECT>::Unflag(G4FastListNode<OBJECT>* __node)
419 __node->fAttachedToList = false;
420 __node->fListRef.reset();
424 template<class OBJECT>
425 OBJECT* G4FastList<OBJECT>::pop_back()
427 if (fNbObjects == 0) return 0;
428 G4FastListNode<OBJECT> * __aNode = fBoundary.GetPrevious();
431 return __aNode->GetObject();
434 template<class OBJECT>
435 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::pop(OBJECT* __obj)
437 G4FastListNode<OBJECT>* __node = Unflag(__obj);
438 iterator __next(__node->GetNext());
443 template<class OBJECT>
444 typename G4FastList<OBJECT>::iterator
445 G4FastList<OBJECT>::pop(G4FastListNode<OBJECT>* __node)
448 iterator __next(__node->GetNext());
453 template<class OBJECT>
454 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::erase(OBJECT* __obj)
456 G4FastListNode<OBJECT>* __next_node = EraseListNode(__obj);
461 iterator __next(__next_node);
465 template<class OBJECT>
466 G4FastListNode<OBJECT>* G4FastList<OBJECT>::EraseListNode(OBJECT* __obj)
468 G4FastListNode<OBJECT>* __node = Unflag(__obj);
469 __node->DetachYourSelf();
470 G4FastListNode<OBJECT>* __next = __node->GetNext();
476 template<class OBJECT>
477 void G4FastList<OBJECT>::DeleteObject(OBJECT*)
482 template<class OBJECT>
483 void G4FastList<OBJECT>::remove(OBJECT* __obj)
488 template<class OBJECT>
489 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::pop(iterator __first,
492 if (fNbObjects == 0) return iterator(&fBoundary);
494 while (__first != __last)
496 if (__first.fpNode) __first = pop(*__first);
501 template<class OBJECT>
502 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::erase(iterator __first,
505 if (fNbObjects == 0) return iterator(&fBoundary);
507 while (__first != __last)
509 if (__first.fpNode) __first = erase(*__first);
514 template<class OBJECT>
515 void G4FastList<OBJECT>::clear()
517 erase(begin(), end());
520 template<class OBJECT>
521 void G4FastList<OBJECT>::transferTo(G4FastList<OBJECT>* __destination)
523 if (fNbObjects == 0) return;
525 if (__destination->fNbObjects == 0)
528 if(__destination->fWatchers.empty()==false)
530 typename WatcherSet::iterator it = __destination->fWatchers.begin();
531 typename WatcherSet::iterator _end = __destination->fWatchers.end();
533 // G4cout << "G4FastList<OBJECT>::transferTo --- Watcher size = "
534 // << __destination->fWatchers.size()
537 for (; it != _end; it++)
539 for(iterator it2 = this->begin() ;
540 it2 != this->end(); ++it2
543 (*it)->NotifyAddObject(*it2, this);
548 __destination->fNbObjects = this->fNbObjects;
550 __destination->fBoundary.SetNext(fBoundary.GetNext());
551 __destination->fBoundary.SetPrevious(fBoundary.GetPrevious());
552 fBoundary.GetNext()->SetPrevious(&__destination->fBoundary);
553 fBoundary.GetPrevious()->SetNext(&__destination->fBoundary);
557 if(__destination->fWatchers.empty()==false)
559 typename WatcherSet::iterator it = __destination->fWatchers.begin();
560 typename WatcherSet::iterator _end = __destination->fWatchers.end();
562 for (; it != _end; it++)
564 for(iterator it2 = this->begin() ;
565 it2 != this->end(); ++it2)
567 (*it)->NotifyAddObject(*it2, this);
572 node* lastNode = __destination->fBoundary.GetPrevious();
573 lastNode->SetNext(fBoundary.GetNext());
574 fBoundary.GetNext()->SetPrevious(lastNode);
575 __destination->fBoundary.SetPrevious(fBoundary.GetPrevious());
576 fBoundary.GetPrevious()->SetNext(&__destination->fBoundary);
578 __destination->fNbObjects += this->fNbObjects;
582 this->fBoundary.SetPrevious(&this->fBoundary);
583 this->fBoundary.SetNext(&this->fBoundary);
585 fListRef->fpList = __destination;
588 //____________________________________________________________
590 // G4FastList<OBJECT> Utils
591 //____________________________________________________________
593 template<class OBJECT>
594 G4FastListNode<OBJECT>* G4FastList<OBJECT>::__GetNode(OBJECT* __obj)
596 G4FastListNode<OBJECT>* __node = GetNode(__obj);
597 // TODO : complete the exception
600 G4ExceptionDescription exceptionDescription;
601 exceptionDescription << "The object ";
602 exceptionDescription << " was not connected to any trackList ";
603 G4Exception("G4FastList<OBJECT>::Unflag", "G4FastList003",
604 FatalErrorInArgument, exceptionDescription);
610 template<class OBJECT>
611 G4FastListNode<OBJECT>* G4FastList<OBJECT>::GetNode(OBJECT* __obj)
613 G4FastListNode<OBJECT>* __node = __obj->GetListNode();
617 template<class OBJECT>
618 void G4FastList<OBJECT>::SetNode(OBJECT* __obj,
619 G4FastListNode<OBJECT>* __node)
621 __obj->SetListNode(__node);
624 template<class OBJECT>
625 G4FastList<OBJECT>* G4FastList<OBJECT>::GetList(OBJECT* __obj)
627 G4FastListNode<OBJECT>* __node = GetNode(__obj);
629 if (__node == 0) return 0;
630 if (__node->fListRef == nullptr) return 0;
632 return __node->fListRef->fpTrackList;
635 template<class OBJECT>
637 G4FastList<OBJECT>::GetList(G4FastListNode<OBJECT>* __node)
639 if (__node == 0) return 0;
640 if (__node->fListRef == nullptr) return 0;
642 return __node->fListRef->fpList;
645 template<class OBJECT>
646 void G4FastList<OBJECT>::Pop(OBJECT* __obj)
648 G4FastListNode<OBJECT>* __node = G4FastList<OBJECT>::GetNode(__obj);
649 G4FastList<OBJECT>* __list = G4FastList<OBJECT>::GetList(__node);
650 if (__list) __list->pop(__node);
653 //#endif /* G4FASTLIST_ICC_*/