// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // // Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr) // // History: // ----------- // 10 Oct 2011 M.Karamitros created // // ------------------------------------------------------------------- //#ifndef G4FASTLIST_ICC_ //#define G4FASTLIST_ICC_ //*********************************************************** // TrackList_iterator template OBJECT* G4FastList_iterator::operator*() { if (fpNode == nullptr) return nullptr; return fpNode->GetObject(); } template OBJECT* G4FastList_iterator::operator->() { if (fpNode == nullptr) return nullptr; return fpNode->GetObject(); } template const OBJECT* G4FastList_iterator::operator*() const { if (fpNode == 0) return 0; return fpNode->GetObject(); } template const OBJECT* G4FastList_iterator::operator->() const { if (fpNode == 0) return 0; return fpNode->GetObject(); } //*********************************************************** // TrackNodeList template G4FastListNode::G4FastListNode(OBJECT* track) : fpObject(track), fpPrevious(nullptr), fpNext(nullptr) { fAttachedToList = false; } template G4FastListNode::~G4FastListNode() { if (fListRef && fListRef->fpList) { fListRef->fpList->pop(this); } } template void G4FastListNode::DetachYourSelf() { if(fpObject) { fpObject->SetListNode(nullptr); } } //*********************************************************** template G4FastList::G4FastList() : fBoundary() { fListRef.reset(new _ListRef >(this)); fNbObjects = 0; fBoundary.SetPrevious(&fBoundary); fBoundary.SetNext(&fBoundary); fBoundary.fAttachedToList = true; fpNodeInManyLists = nullptr; } // should not be used template G4FastList::G4FastList(const G4FastList& /*other*/) : fBoundary() { // One track should not belong to two different trackLists fNbObjects = 0; fpNodeInManyLists = 0; } template G4FastList& G4FastList::operator=(const G4FastList& other) { // One track should not belong to two different trackList if (this == &other) return *this; // handle self assignment //assignment operator return *this; } template G4FastList::~G4FastList() { if (fNbObjects != 0) { G4FastListNode * __stackedTrack = fBoundary.GetNext(); G4FastListNode * __nextStackedTrack; // delete tracks in the stack while (__stackedTrack && __stackedTrack != &(fBoundary)) { __nextStackedTrack = __stackedTrack->GetNext(); OBJECT* __obj = __stackedTrack->GetObject(); delete __stackedTrack; __stackedTrack = nullptr; if (__obj) { ////////////// DeleteObject(__obj); __obj = nullptr; ////////////// } __stackedTrack = __nextStackedTrack; } } fNbObjects = 0; auto it = fWatchers.begin(); auto _end = fWatchers.end(); for (; it != _end; it++) { (*it)->NotifyDeletingList(this); (*it)->StopWatching(this, false); } if (fpNodeInManyLists) { delete fpNodeInManyLists; fpNodeInManyLists = nullptr; } } template bool G4FastList::empty() const { return (fNbObjects == 0); } template typename G4FastList::iterator G4FastList::begin() { return iterator(fBoundary.GetNext()); } template typename G4FastList::const_iterator G4FastList::begin() const { return const_iterator(fBoundary.GetNext()); } template typename G4FastList::iterator G4FastList::end() { return iterator(&(fBoundary)); } template typename G4FastList::const_iterator G4FastList::end() const { return const_iterator(&(fBoundary)); } // return an iterator that contains an empty node // use for boundary checking only template void G4FastList::push_front(OBJECT* __obj) { insert(begin(), __obj); } template void G4FastList::push_back(OBJECT* __obj) { insert(end(), __obj); } template bool G4FastList::Holds(const OBJECT* __obj) const { node* __node = GetNode(__obj); if(__node == 0) return false; return (__node->fListRef->fpList == this); } // TODO: A revoir template G4FastListNode* G4FastList::Flag(OBJECT* __obj) { G4FastListNode* __node = GetNode(__obj); if (__node != nullptr) { // Suggestion move the node to this list if (__node->fAttachedToList) { G4ExceptionDescription exceptionDescription; exceptionDescription << "An object"; exceptionDescription << " is already attached to a TrackList "; G4Exception("G4FastList::Flag", "G4FastList001", FatalErrorInArgument, exceptionDescription); } } else { __node = new G4FastListNode(__obj); SetNode(__obj,__node); } __node->fAttachedToList = true; __node->fListRef = fListRef; return __node; } template G4FastListNode* G4FastList::CreateNode(OBJECT* __obj) { G4FastListNode* __listNode = Flag(__obj); return __listNode; } template void G4FastList::Hook(G4FastListNode* __position, G4FastListNode* __toHook) { /* __toHook->SetNext(__position); __toHook->SetPrevious(__position->GetPrevious()); __position->GetPrevious()->SetNext(__toHook); __position->SetPrevious(__toHook); */ G4FastListNode* __previous = __position->GetPrevious(); __toHook->SetPrevious(__previous); __toHook->SetNext(__position); __position->SetPrevious(__toHook); __previous->SetNext(__toHook); /* if (fNbObjects == 0) { // DEBUG // G4cout << "fNbObjects == 0" << G4endl; fpStart = __toHook; fpFinish = __toHook; __toHook->SetNext(&fBoundary); __toHook->SetPrevious(&fBoundary); //fBoundary.SetNext(__toHook); fBoundary.SetPrevious(__toHook); } else if (__position == &fBoundary) { // DEBUG // G4cout << "__position == &fBoundary" << G4endl; fpFinish->SetNext(__toHook); __toHook->SetPrevious(fpFinish); __toHook->SetNext(&fBoundary); fBoundary.SetPrevious(__toHook); fpFinish = __toHook; } else if (__position == fpStart) { // DEBUG // G4cout << "__position == fStart" << G4endl; __toHook->SetPrevious(&fBoundary); //fBoundary.SetNext(__toHook); __toHook->SetNext(fpStart); fpStart->SetPrevious(__toHook); fpStart = __toHook; } else { // DEBUG // G4cout << "else" << G4endl; G4FastListNode* __previous = __position->GetPrevious(); __toHook->SetPrevious(__previous); __toHook->SetNext(__position); __position->SetPrevious(__toHook); __previous->SetNext(__toHook); } */ fNbObjects++; if(fWatchers.empty() == false) { auto it = fWatchers.begin(); auto _end = fWatchers.end(); for (; it != _end; it++) { (*it)->NotifyAddObject(__toHook->GetObject(), this); } } } template void G4FastListNode::UnHook() { G4FastListNode* __next_node = this->fpNext; G4FastListNode* __prev_node = this->fpPrevious; if (__prev_node) { __prev_node->fpNext = __next_node; } if (__next_node) { __next_node->fpPrevious = __prev_node; } fpNext = nullptr; fpPrevious = nullptr; } template void G4FastList::Unhook(G4FastListNode* __toUnHook) { __toUnHook->UnHook(); fNbObjects--; auto it = fWatchers.begin(); auto _end = fWatchers.end(); for (; it != _end; it++) { (*it)->NotifyRemoveObject(__toUnHook->GetObject(), this); } } template typename G4FastList::iterator G4FastList::insert(typename G4FastList::iterator __position, OBJECT* __obj) { G4FastListNode* __node = CreateNode(__obj); Hook(__position.fpNode, __node); return iterator(__node); } //____________________________________________________________________ // // WITHDRAW FROM LIST //____________________________________________________________________ template void G4FastList::CheckFlag(G4FastListNode* __node) { if (__node->fListRef->fpList != this) { G4ExceptionDescription exceptionDescription; exceptionDescription << "The object " << " is not correctly linked to a G4FastList." << G4endl << "You are probably trying to withdraw this object " << "from the list but it probably does not belong to " << "this fast list." << G4endl; G4Exception("G4FastList::CheckFlag", "G4FastList002", FatalErrorInArgument, exceptionDescription); } } template G4FastListNode* G4FastList::Unflag(OBJECT* __obj) { G4FastListNode* __node = __GetNode(__obj); CheckFlag(__node); __node->fAttachedToList = false; __node->fListRef.reset(); return __node; } template void G4FastList::Unflag(G4FastListNode* __node) { CheckFlag(__node); __node->fAttachedToList = false; __node->fListRef.reset(); return; } template OBJECT* G4FastList::pop_back() { if (fNbObjects == 0) return 0; G4FastListNode * __aNode = fBoundary.GetPrevious(); Unhook(__aNode); Unflag(__aNode); return __aNode->GetObject(); } template typename G4FastList::iterator G4FastList::pop(OBJECT* __obj) { G4FastListNode* __node = Unflag(__obj); iterator __next(__node->GetNext()); Unhook(__node); return __next; } template typename G4FastList::iterator G4FastList::pop(G4FastListNode* __node) { Unflag(__node); iterator __next(__node->GetNext()); Unhook(__node); return __next; } template typename G4FastList::iterator G4FastList::erase(OBJECT* __obj) { G4FastListNode* __next_node = EraseListNode(__obj); ////////////////// DeleteObject(__obj); __obj = nullptr; ////////////////// iterator __next(__next_node); return __next; } template G4FastListNode* G4FastList::EraseListNode(OBJECT* __obj) { G4FastListNode* __node = Unflag(__obj); __node->DetachYourSelf(); G4FastListNode* __next = __node->GetNext(); Unhook(__node); delete __node; return __next; } template void G4FastList::DeleteObject(OBJECT*) { // delete __obj; } template void G4FastList::remove(OBJECT* __obj) { this->erase(__obj); } template typename G4FastList::iterator G4FastList::pop(iterator __first, iterator __last) { if (fNbObjects == 0) return iterator(&fBoundary); while (__first != __last) { if (__first.fpNode) __first = pop(*__first); } return __last; } template typename G4FastList::iterator G4FastList::erase(iterator __first, iterator __last) { if (fNbObjects == 0) return iterator(&fBoundary); while (__first != __last) { if (__first.fpNode) __first = erase(*__first); } return __last; } template void G4FastList::clear() { erase(begin(), end()); } template void G4FastList::transferTo(G4FastList* __destination) { if (fNbObjects == 0) return; if (__destination->fNbObjects == 0) { if(__destination->fWatchers.empty()==false) { auto it = __destination->fWatchers.begin(); auto _end = __destination->fWatchers.end(); // G4cout << "G4FastList::transferTo --- Watcher size = " // << __destination->fWatchers.size() // << G4endl; for (; it != _end; it++) { for(iterator it2 = this->begin() ; it2 != this->end(); ++it2 ) { (*it)->NotifyAddObject(*it2, this); } } } __destination->fNbObjects = this->fNbObjects; __destination->fBoundary.SetNext(fBoundary.GetNext()); __destination->fBoundary.SetPrevious(fBoundary.GetPrevious()); fBoundary.GetNext()->SetPrevious(&__destination->fBoundary); fBoundary.GetPrevious()->SetNext(&__destination->fBoundary); } else { if(__destination->fWatchers.empty()==false) { auto it = __destination->fWatchers.begin(); auto _end = __destination->fWatchers.end(); for (; it != _end; it++) { for(iterator it2 = this->begin() ; it2 != this->end(); ++it2) { (*it)->NotifyAddObject(*it2, this); } } } node* lastNode = __destination->fBoundary.GetPrevious(); lastNode->SetNext(fBoundary.GetNext()); fBoundary.GetNext()->SetPrevious(lastNode); __destination->fBoundary.SetPrevious(fBoundary.GetPrevious()); fBoundary.GetPrevious()->SetNext(&__destination->fBoundary); __destination->fNbObjects += this->fNbObjects; } fNbObjects = 0; this->fBoundary.SetPrevious(&this->fBoundary); this->fBoundary.SetNext(&this->fBoundary); fListRef->fpList = __destination; } //____________________________________________________________ // // G4FastList Utils //____________________________________________________________ template G4FastListNode* G4FastList::__GetNode(OBJECT* __obj) { G4FastListNode* __node = GetNode(__obj); // TODO : complete the exception if (__node == nullptr) { G4ExceptionDescription exceptionDescription; exceptionDescription << "The object "; exceptionDescription << " was not connected to any trackList "; G4Exception("G4FastList::Unflag", "G4FastList003", FatalErrorInArgument, exceptionDescription); return nullptr; } return __node; } template G4FastListNode* G4FastList::GetNode(OBJECT* __obj) { G4FastListNode* __node = __obj->GetListNode(); return __node; } template void G4FastList::SetNode(OBJECT* __obj, G4FastListNode* __node) { __obj->SetListNode(__node); } template G4FastList* G4FastList::GetList(OBJECT* __obj) { G4FastListNode* __node = GetNode(__obj); if (__node == 0) return 0; if (__node->fListRef == nullptr) return 0; return __node->fListRef->fpTrackList; } template G4FastList* G4FastList::GetList(G4FastListNode* __node) { if (__node == nullptr) return nullptr; if (__node->fListRef == nullptr) return nullptr; return __node->fListRef->fpList; } template void G4FastList::Pop(OBJECT* __obj) { G4FastListNode* __node = G4FastList::GetNode(__obj); G4FastList* __list = G4FastList::GetList(__node); if (__list) __list->pop(__node); } //#endif /* G4FASTLIST_ICC_*/