// // ******************************************************************** // * 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 // The code is developed in the framework of the ESA AO7146 // // We would be very happy hearing from you, send us your feedback! :) // // In order for Geant4-DNA to be maintained and still open-source, // article citations are crucial. // If you use Geant4-DNA chemistry and you publish papers about your software, // in addition to the general paper on Geant4-DNA: // // Int. J. Model. Simul. Sci. Comput. 1 (2010) 157–178 // // we would be very happy if you could please also cite the following // reference papers on chemistry: // // J. Comput. Phys. 274 (2014) 841-882 // Prog. Nucl. Sci. Tec. 2 (2011) 503-508 #pragma once #include "globals.hh" #include "G4ReferenceCountedHandle.hh" #include #include #include //#include "G4ManyFastLists.hh" template class G4FastList; template class G4FastList_Boundary; template struct G4FastList_iterator; template struct G4FastList_const_iterator; template class G4ManyFastLists; template struct G4ManyFastLists_iterator; template struct sortWatcher; /** Comments : * - A track cannot belong to two different track lists * - Erase a given track is constant complexity * - This development was thought to be used together with G4IT */ #ifndef TYPE_WRAPPER #define TYPE_WRAPPER template < typename T> struct type_wrapper { using type = T; }; #endif template struct _ListRef { using traits_type = type_wrapper; using mli_traits_type = type_wrapper>; //#ifdef WIN32 // friend typename traits_type::type; // friend typename traits_type::type::node; // friend typename mli_traits_type::type; ////#elif defined(__clang__) //// friend T; //// friend T::node; //// friend G4ManyFastLists_iterator; //#else // friend class traits_type::type; // friend class traits_type::type::node; // friend class mli_traits_type::type; //#endif LIST* fpList; // protected: inline _ListRef(LIST* __list) : fpList(__list) { ; } }; /** * G4FastListNode is the entity actually stored * by the G4FastList. A G4FastListNode should * belong only to one list. Also, an object * should belong only to one list. */ template class G4FastListNode { using ObjectW = type_wrapper; using LIST = G4FastList; // typedef type_wrapper > ListW; using ListW = type_wrapper>; // typedef type_wrapper > ManyListsW; using ManyListsW = type_wrapper>; // typedef type_wrapper > ManyListsIteratorW; using ManyListsIteratorW = type_wrapper>; //#ifdef WIN32 // friend typename ListW::type; // friend typename ManyListsW::type; // friend typename ManyListsIteratorW::type; ////#elif defined(__clang__) //// friend T; //// friend G4ManyFastLists_iterator; //#else // friend class ListW::type; // friend class ManyListsW::type; // friend struct ManyListsIteratorW::type; //#endif public: ~G4FastListNode(); OBJECT* GetObject() { return fpObject; } const OBJECT* GetObject() const { return fpObject; } G4FastListNode* GetNext() { return fpNext; } const G4FastListNode* GetNext() const { return fpNext; } G4FastListNode* GetPrevious() { return fpPrevious; } const G4FastListNode* GetPrevious() const { return fpPrevious; } bool IsAttached() { return fAttachedToList; } //protected: /** Default constructor */ G4FastListNode(OBJECT* track = nullptr); void SetNext(G4FastListNode* node) { fpNext = node; } void SetPrevious(G4FastListNode* node) { fpPrevious = node; } void SetAttachedToList(bool flag) { fAttachedToList = flag; } void UnHook(); void DetachYourSelf(); bool fAttachedToList; G4shared_ptr<_ListRef > > fListRef; OBJECT* fpObject; G4FastListNode* fpPrevious; G4FastListNode* fpNext; }; /** * G4FastList is used by G4TrackHolder to save * G4IT tracks only. Its advantage lies to a fast * search of a track in this list. */ template class G4FastList { protected: G4int fNbObjects; // G4FastListNode * fpStart; // G4FastListNode * fpFinish; G4shared_ptr<_ListRef > > fListRef; G4FastListNode fBoundary; // Must be empty and link to the last non-empty node of the list // and to the first non-empty node of the list (begin()) // The iterator returned by end() is linked to this empty node public: class Watcher { public: enum Priority { eExtreme, eHigh, eNormal, eLow, eVeryLow }; using list = G4FastList; Watcher() { fPriority = Priority::eVeryLow; } virtual ~Watcher() { auto it = fWatching.begin(); auto end = fWatching.end(); for(;it!=end;it++) { (*it)->RemoveWatcher(this); } } virtual G4String GetWatcherName(){ return ""; } Priority GetPriority() const{ return fPriority; } // =============================== // NOTIFICATIONS void NotifyDeletingList(G4FastList*){;} // used by PriorityList & ManyFastLists virtual void NotifyAddObject(OBJECT*, G4FastList*){;} virtual void NotifyRemoveObject(OBJECT*, G4FastList*){;} // void NotifyEmpty(OBJECT*, G4FastList*){;} // =============================== void Watch(G4FastList* fastList) { fWatching.insert(fastList); fastList->AddWatcher(this); } void StopWatching(G4FastList* fastList, bool removeWatcher = true) { auto it = fWatching.find(fastList); if(it == fWatching.end()) return; //TODO: exception? fWatching.erase(it); if(removeWatcher) fastList->RemoveWatcher(this); } protected: Priority fPriority; private: std::set*> fWatching; }; template class TWatcher : public Watcher { public: TWatcher() : Watcher(){} virtual ~TWatcher()= default; virtual G4String GetWatcherName() { return typeid(WATCHER_TYPE).name(); } }; protected: using WatcherSet = std::set::Watcher*, sortWatcher>; WatcherSet fWatchers; G4FastListNode >* fpNodeInManyLists; public: using object = OBJECT; using iterator = G4FastList_iterator; using const_iterator = G4FastList_const_iterator; using node = G4FastListNode; G4FastList(); ~G4FastList(); void SetListNode(G4FastListNode >* __node) { fpNodeInManyLists = __node; } G4FastListNode >* GetListNode() { return fpNodeInManyLists; } void AddWatcher(Watcher* watcher) { fWatchers.insert(watcher); } void RemoveWatcher(Watcher* watcher) { auto it = fWatchers.find(watcher); if(it == fWatchers.end()) return; //TODO: exception? fWatchers.erase(it); } inline OBJECT* back() { // if (fNbObjects != 0) return fpFinish->GetObject(); if (fNbObjects != 0) return fBoundary.GetPrevious()->GetObject(); return 0; } inline G4int size() const { return fNbObjects; } inline bool empty() const; iterator insert(iterator /*position*/, OBJECT*); inline iterator begin(); inline const_iterator begin() const; inline iterator end(); inline const_iterator end() const; /** * return an iterator that contains an empty node * use for boundary checking only */ bool Holds(const OBJECT*) const; inline void push_front(OBJECT* __track); inline void push_back(OBJECT* __track); OBJECT* pop_back(); void remove(OBJECT*); iterator pop(OBJECT*); iterator pop(G4FastListNode*); iterator pop(iterator __first, iterator __last); iterator erase(OBJECT*); /** * Complexity = constant * By storing the node inside the object, we avoid * searching through all the container. */ iterator erase(iterator __first, iterator __last); /** * Complexity = linear in size between __first and __last */ void clear(); void transferTo(G4FastList*); /** * Complexity = constant */ static G4FastListNode* GetNode(OBJECT*); static void SetNode(OBJECT* __obj, G4FastListNode* __node); static G4FastList* GetList(OBJECT*); static G4FastList* GetList(G4FastListNode* __trackListNode); static void Pop(OBJECT*); protected: G4FastListNode* CreateNode(OBJECT*); static G4FastListNode* __GetNode(OBJECT*); G4FastListNode* Flag(OBJECT*); G4FastListNode* Unflag(OBJECT*); void Unflag(G4FastListNode* __trackListNode); void CheckFlag(G4FastListNode*); void DeleteObject(OBJECT*); void Hook(G4FastListNode* /*position*/, G4FastListNode* /*toHook*/); void Unhook(G4FastListNode*); G4FastListNode* EraseListNode(OBJECT*); private: G4FastList(const G4FastList& other); G4FastList & operator=(const G4FastList &right); G4bool operator==(const G4FastList &right) const; G4bool operator!=(const G4FastList &right) const; }; template struct sortWatcher { bool operator()(const typename G4FastList::Watcher* left, const typename G4FastList::Watcher* right) const { if(left && right) { if(left->GetPriority() != right->GetPriority()) { return left->GetPriority() < right->GetPriority(); } return left < right; } return false; } }; /** * G4FastList_iterator enables to go through * the tracks contained by a list. */ template struct G4FastList_iterator { // friend class G4FastList; using _Self = G4FastList_iterator; using _Node = G4FastListNode; G4FastList_iterator() = default; explicit G4FastList_iterator(_Node* __x) : fpNode(__x) { } G4FastList_iterator(const G4FastList_iterator& right) = default; _Self& operator=(const G4FastList_iterator& right) = default; _Node* GetNode() { return fpNode; } const _Node* GetNode() const { return fpNode; } OBJECT* operator*(); const OBJECT* operator*() const; OBJECT* operator->(); const OBJECT* operator->() const; _Self& operator++() { fpNode = fpNode->GetNext(); return *this; } _Self operator++(int) { _Self __tmp = *this; fpNode = fpNode->GetNext(); return __tmp; } _Self& operator--() { fpNode = fpNode->GetPrevious(); return *this; } _Self operator--(int) { _Self __tmp = *this; fpNode = fpNode->GetPrevious(); return __tmp; } G4bool operator==(const _Self& __x) const { return (fpNode == __x.fpNode); } G4bool operator!=(const _Self& __x) const { return (fpNode != __x.fpNode); } // private: // The only member points to the G4FastList_iterator element. _Node* fpNode = nullptr; }; /** * G4FastList_iterator enables to go through * the tracks contained by a list. */ template struct G4FastList_const_iterator { // friend class G4FastList; using _Self = G4FastList_const_iterator; using _Node = G4FastListNode; G4FastList_const_iterator() = default; explicit G4FastList_const_iterator(const _Node* __x) : fpNode(__x) { } G4FastList_const_iterator(const G4FastList_const_iterator& right) = default; _Self& operator=(const G4FastList_const_iterator& right) = default; G4FastList_const_iterator(const G4FastList_iterator& right) : fpNode(right.GetNode()) { } _Self& operator=(const G4FastList_iterator& right) { fpNode = right.GetNode(); return *this; } const OBJECT* operator*() const { if(fpNode == nullptr) return nullptr; return fpNode->GetObject(); } const OBJECT* operator->() const { if(fpNode == 0) return 0; return fpNode->GetObject(); } _Self& operator++() { fpNode = fpNode->GetNext(); return *this; } _Self operator++(int) { _Self __tmp = *this; fpNode = fpNode->GetNext(); return __tmp; } _Self& operator--() { fpNode = fpNode->GetPrevious(); return *this; } _Self operator--(int) { _Self __tmp = *this; fpNode = fpNode->GetPrevious(); return __tmp; } G4bool operator==(const _Self& __x) const { return (fpNode == __x.fpNode); } G4bool operator!=(const _Self& __x) const { return (fpNode != __x.fpNode); } // private: // The only member points to the G4FastList_iterator element. const _Node* fpNode = nullptr; }; #include "G4FastList.icc"