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 std::set<Watcher*>::iterator it = fWatchers.begin();
 
  164     typename std::set<Watcher*>::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     typename std::set<Watcher*>::iterator it = fWatchers.begin();
 
  328     typename std::set<Watcher*>::iterator _end = fWatchers.end();
 
  330     for (; it != _end; it++)
 
  332       (*it)->NotifyNewObject(__toHook->GetObject(), this);
 
  336 template<class OBJECT>
 
  337   void G4FastListNode<OBJECT>::UnHook()
 
  339     G4FastListNode<OBJECT>* __next_node = this->fpNext;
 
  340     G4FastListNode<OBJECT>* __prev_node = this->fpPrevious;
 
  344       __prev_node->fpNext = __next_node;
 
  349       __next_node->fpPrevious = __prev_node;
 
  355 template<class OBJECT>
 
  356   void G4FastList<OBJECT>::Unhook(G4FastListNode<OBJECT>* __toUnHook)
 
  358     __toUnHook->UnHook();
 
  362     typename std::set<Watcher*>::iterator it = fWatchers.begin();
 
  363     typename std::set<Watcher*>::iterator _end = fWatchers.end();
 
  365     for (; it != _end; it++)
 
  367       (*it)->NotifyRemoveObject(__toUnHook->GetObject(), this);
 
  371 template<class OBJECT>
 
  372   typename G4FastList<OBJECT>::iterator
 
  373   G4FastList<OBJECT>::insert(typename G4FastList<OBJECT>::iterator __position,
 
  376     G4FastListNode<OBJECT>* __node = CreateNode(__obj);
 
  377     Hook(__position.fpNode, __node);
 
  378     return iterator(__node);
 
  381 //____________________________________________________________________
 
  383 //                      WITHDRAW FROM LIST
 
  384 //____________________________________________________________________
 
  386 template<class OBJECT>
 
  387   void G4FastList<OBJECT>::CheckFlag(G4FastListNode<OBJECT>* __node)
 
  389     if (__node->fListRef->fpList != this)
 
  391       G4ExceptionDescription exceptionDescription;
 
  392       exceptionDescription << "The object "
 
  393       << " is not correctly linked to a G4FastList." << G4endl
 
  394       << "You are probably trying to withdraw this object "
 
  395       << "from the list but it probably does not belong to "
 
  396       << "this fast list." << G4endl;
 
  397       G4Exception("G4FastList<OBJECT>::CheckFlag", "G4FastList002",
 
  398                   FatalErrorInArgument, exceptionDescription);
 
  402 template<class OBJECT>
 
  403   G4FastListNode<OBJECT>* G4FastList<OBJECT>::Unflag(OBJECT* __obj)
 
  405     G4FastListNode<OBJECT>* __node = __GetNode(__obj);
 
  407     __node->fAttachedToList = false;
 
  408     __node->fListRef.reset();
 
  412 template<class OBJECT>
 
  413   void G4FastList<OBJECT>::Unflag(G4FastListNode<OBJECT>* __node)
 
  416     __node->fAttachedToList = false;
 
  417     __node->fListRef.reset();
 
  421 template<class OBJECT>
 
  422   OBJECT* G4FastList<OBJECT>::pop_back()
 
  424     if (fNbObjects == 0) return 0;
 
  425     G4FastListNode<OBJECT> * __aNode = fBoundary.GetPrevious();
 
  428     return __aNode->GetObject();
 
  431 template<class OBJECT>
 
  432   typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::pop(OBJECT* __obj)
 
  434     G4FastListNode<OBJECT>* __node = Unflag(__obj);
 
  435     iterator __next(__node->GetNext());
 
  440 template<class OBJECT>
 
  441   typename G4FastList<OBJECT>::iterator
 
  442   G4FastList<OBJECT>::pop(G4FastListNode<OBJECT>* __node)
 
  445     iterator __next(__node->GetNext());
 
  450 template<class OBJECT>
 
  451   typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::erase(OBJECT* __obj)
 
  453     G4FastListNode<OBJECT>* __next_node = EraseListNode(__obj);
 
  458     iterator __next(__next_node);
 
  462 template<class OBJECT>
 
  463   G4FastListNode<OBJECT>* G4FastList<OBJECT>::EraseListNode(OBJECT* __obj)
 
  465     G4FastListNode<OBJECT>* __node = Unflag(__obj);
 
  466     __node->DetachYourSelf();
 
  467     G4FastListNode<OBJECT>* __next = __node->GetNext();
 
  473 template<class OBJECT>
 
  474   void G4FastList<OBJECT>::DeleteObject(OBJECT*)
 
  479 template<class OBJECT>
 
  480   void G4FastList<OBJECT>::remove(OBJECT* __obj)
 
  485 template<class OBJECT>
 
  486   typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::pop(iterator __first,
 
  489     if (fNbObjects == 0) return iterator(&fBoundary);
 
  491     while (__first != __last)
 
  493       if (__first.fpNode) __first = pop(*__first);
 
  498 template<class OBJECT>
 
  499   typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::erase(iterator __first,
 
  502     if (fNbObjects == 0) return iterator(&fBoundary);
 
  504     while (__first != __last)
 
  506       if (__first.fpNode) __first = erase(*__first);
 
  511 template<class OBJECT>
 
  512   void G4FastList<OBJECT>::clear()
 
  514     erase(begin(), end());
 
  517 template<class OBJECT>
 
  518   void G4FastList<OBJECT>::transferTo(G4FastList<OBJECT>* __destination)
 
  520     if (fNbObjects == 0) return;
 
  522     if (__destination->fNbObjects == 0)
 
  524       __destination->fNbObjects = this->fNbObjects;
 
  526       __destination->fBoundary.SetNext(fBoundary.GetNext());
 
  527       __destination->fBoundary.SetPrevious(fBoundary.GetPrevious());
 
  528       fBoundary.GetNext()->SetPrevious(&__destination->fBoundary);
 
  529       fBoundary.GetPrevious()->SetNext(&__destination->fBoundary);
 
  533       node* lastNode = __destination->fBoundary.GetPrevious();
 
  534       lastNode->SetNext(fBoundary.GetNext());
 
  535       fBoundary.GetNext()->SetPrevious(lastNode);
 
  536       __destination->fBoundary.SetPrevious(fBoundary.GetPrevious());
 
  537       fBoundary.GetPrevious()->SetNext(&__destination->fBoundary);
 
  539       __destination->fNbObjects += this->fNbObjects;
 
  543     this->fBoundary.SetPrevious(&this->fBoundary);
 
  544     this->fBoundary.SetNext(&this->fBoundary);
 
  546     fListRef->fpList = __destination;
 
  549 //____________________________________________________________
 
  551 //                      G4FastList<OBJECT> Utils
 
  552 //____________________________________________________________
 
  554 template<class OBJECT>
 
  555   G4FastListNode<OBJECT>* G4FastList<OBJECT>::__GetNode(OBJECT* __obj)
 
  557     G4FastListNode<OBJECT>* __node = GetNode(__obj);
 
  558     // TODO : complete the exception
 
  561       G4ExceptionDescription exceptionDescription;
 
  562       exceptionDescription << "The object ";
 
  563       exceptionDescription << " was not connected to any trackList ";
 
  564       G4Exception("G4FastList<OBJECT>::Unflag", "G4FastList003",
 
  565                   FatalErrorInArgument, exceptionDescription);
 
  571 template<class OBJECT>
 
  572   G4FastListNode<OBJECT>* G4FastList<OBJECT>::GetNode(OBJECT* __obj)
 
  574     G4FastListNode<OBJECT>* __node = __obj->GetListNode();
 
  578 template<class OBJECT>
 
  579   void G4FastList<OBJECT>::SetNode(OBJECT* __obj,
 
  580                                    G4FastListNode<OBJECT>* __node)
 
  582     __obj->SetListNode(__node);
 
  585 template<class OBJECT>
 
  586   G4FastList<OBJECT>* G4FastList<OBJECT>::GetList(OBJECT* __obj)
 
  588     G4FastListNode<OBJECT>* __node = GetNode(__obj);
 
  590     if (__node == 0) return 0;
 
  591     if (__node->fListRef == 0) return 0;
 
  593     return __node->fListRef->fpTrackList;
 
  596 template<class OBJECT>
 
  598   G4FastList<OBJECT>::GetList(G4FastListNode<OBJECT>* __node)
 
  600     if (__node == 0) return 0;
 
  601     if (__node->fListRef == 0) return 0;
 
  603     return __node->fListRef->fpList;
 
  606 template<class OBJECT>
 
  607   void G4FastList<OBJECT>::Pop(OBJECT* __obj)
 
  609     G4FastListNode<OBJECT>* __node = G4FastList<OBJECT>::GetNode(__obj);
 
  610     G4FastList<OBJECT>* __list = G4FastList<OBJECT>::GetList(__node);
 
  611     if (__list) __list->pop(__node);
 
  614 //#endif /* G4FASTLIST_ICC_*/