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_*/