Files
2023-12-08 10:43:34 +01:00

424 lines
11 KiB
C++

//
// ********************************************************************
// * 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. *
// ********************************************************************
//
/*
* G4ManyFastLists.hh
*
* Created on: 17 nov. 2014
* Author: kara
*/
#pragma once
#include "G4FastList.hh"
#include <set>
template<class OBJECT>
struct G4ManyFastLists_iterator;
/*
* Roll over many list as if it was one
*/
template<class OBJECT>
class G4ManyFastLists : public G4FastList<OBJECT>::Watcher
{
protected:
using ManyLists = G4FastList<G4FastList<OBJECT>>;
ManyLists fAssociatedLists;
// TODO use "marked list" insted of vector
using WatcherSet = std::set<typename G4FastList<OBJECT>::Watcher*,
sortWatcher<OBJECT>>;
WatcherSet* fMainListWatchers;
public:
using iterator = G4ManyFastLists_iterator<OBJECT>;
G4ManyFastLists() : G4FastList<OBJECT>::Watcher(),
fAssociatedLists(), fMainListWatchers(nullptr)
{
}
~G4ManyFastLists() override = default;
virtual void NotifyDeletingList(G4FastList<OBJECT>* __list)
{
fAssociatedLists.pop(__list);
}
void AddGlobalWatcher(typename G4FastList<OBJECT>::Watcher* watcher)
{
if(fMainListWatchers == nullptr)
{
fMainListWatchers = new WatcherSet();
}
fMainListWatchers->insert(watcher);
typename ManyLists::iterator it = fAssociatedLists.begin();
typename ManyLists::iterator _end = fAssociatedLists.end();
for(;it != _end ;++it)
{
watcher->Watch(*it);
// (*it)->AddWatcher(watcher);
// (*it)->AddWatcher(watcher);
}
}
inline void Add(G4FastList<OBJECT>* __list)
{
if (__list == nullptr) return;
fAssociatedLists.push_back(__list); // TODO use the table doubling tech
//__list->AddWatcher(this);
this->Watch(__list);
if(fMainListWatchers == nullptr) return;
auto it_watcher = fMainListWatchers->begin();
auto end_watcher = fMainListWatchers->end();
// G4cout << "G4ManyFastLists::Add -- N watchers ="
// << fMainListWatchers->size()
// << G4endl;
for(;it_watcher != end_watcher ;++it_watcher)
{
// G4cout << " *** *** *** WATCH --- "
// << (*it_watcher)->GetWatcherName()
// << G4endl;
(*it_watcher)->Watch(__list);
}
if(__list->empty() == false)
{
it_watcher = fMainListWatchers->begin();
for(;it_watcher != end_watcher ;++it_watcher)
{
typename G4FastList<OBJECT>::iterator it_obj = __list->begin();
for(;it_obj != __list->end() ;++it_obj)
{
// G4cout << " *** *** *** NOTIFY ADD OBJ --- "
// << (*it_watcher)->GetWatcherName()
// << G4endl;
(*it_watcher)->NotifyAddObject(*it_obj,__list);
}
}
}
// else
// {
// G4cout << "__list->empty() == true" << G4endl;
// }
/*
typename ManyLists::const_iterator __it = fAssociatedLists
.begin();
typename ManyLists::const_iterator __end = fAssociatedLists
.end();
for (; __it != __end; __it++)
{
assert(*__it);
}
*/
}
inline void Remove(G4FastList<OBJECT>* __list)
{
if (__list == nullptr) return;
fAssociatedLists.pop(__list); // TODO use the table doubling tech
__list->RemoveWatcher(this);
this->StopWatching(__list);
auto it = fMainListWatchers->begin();
auto _end = fMainListWatchers->end();
for(;it != _end ;++it)
{
(*it)->StopWatching(__list);
}
// typename ManyLists::node* __node = __list->GetListNode();
// if(__node)
// {
// __list->SetListNode(0);
// delete __node;
// }
}
inline bool Holds(OBJECT* __track) const
{
typename ManyLists::const_iterator __it = fAssociatedLists.begin();
typename ManyLists::const_iterator __end = fAssociatedLists.end();
for (; __it != __end; __it++)
if ((*__it)->Holds(__track)) return true;
return false;
}
inline size_t size() const
{
size_t __size(0);
for (auto __it : fAssociatedLists)
{
__size += __it->size();
}
return __size;
}
inline void RemoveLists()
{
typename ManyLists::iterator __it = fAssociatedLists.begin();
typename ManyLists::iterator __end = fAssociatedLists.end();
for (; __it != __end; __it++)
{
if (*__it)
{
(*__it)->clear();
typename ManyLists::iterator next = __it;
next++;
Remove(*__it);
typename ManyLists::node* __node = __it.GetNode();
if(__node)
{
__node->GetObject()->SetListNode(nullptr);
delete __node;
}
// delete (*__it);
__it = next;
}
}
fAssociatedLists.clear();
}
inline void ClearLists()
{
typename ManyLists::iterator __it = fAssociatedLists.begin();
typename ManyLists::iterator __end = fAssociatedLists.end();
for (; __it != __end; __it++)
if (*__it) (*__it)->clear();
}
inline iterator begin();
inline iterator end();
void pop(OBJECT*);
};
template<class OBJECT>
struct G4ManyFastLists_iterator
{
using ManyLists = G4FastList<G4FastList<OBJECT>>;
using _Self = G4ManyFastLists_iterator;
using _Node = G4FastListNode<OBJECT>;
G4FastList_iterator<OBJECT> fIterator;
typename ManyLists::iterator fCurrentListIt;
ManyLists* fLists;
private:
G4ManyFastLists_iterator() = default;
public:
explicit G4ManyFastLists_iterator(G4FastList_iterator<OBJECT> __x,
typename ManyLists::iterator __it,
ManyLists* __lists) :
fIterator(__x), fCurrentListIt(__it), fLists(__lists)
{
}
G4ManyFastLists_iterator(const G4ManyFastLists_iterator& __x) = default;
_Self& operator=(const G4ManyFastLists_iterator& __x) = default;
_Node* GetNode()
{
return fIterator.GetNode();
}
G4FastList<OBJECT>* GetTrackList()
{
return *fCurrentListIt;
}
OBJECT* operator*()
{
return *fIterator;
}
const OBJECT* operator*() const
{
return *fIterator;
}
OBJECT* operator->()
{
return *fIterator;
}
const OBJECT* operator->() const
{
return *fIterator;
}
_Self UpdateToNextValidList();
_Self& operator++();
_Self operator++(int)
{
return operator++();
}
_Self&
operator--()
{
if (fLists->empty())
{
fIterator = G4FastList_iterator<OBJECT>();
return *this;
}
if (fCurrentListIt == fLists->begin())
{
if (fIterator == (*fCurrentListIt)->begin())
{
fIterator = G4FastList_iterator<OBJECT>();
return *this;
}
}
if (fCurrentListIt == fLists->end())
{
fCurrentListIt--;
fIterator = (*fCurrentListIt)->end();
}
else if (fIterator == (*fCurrentListIt)->begin())
{
fCurrentListIt--;
fIterator = (*fCurrentListIt)->end();
}
fIterator--;
while (((*fCurrentListIt)->empty() || fIterator.GetNode() == nullptr
|| fIterator.GetNode()->GetObject() == nullptr)
&& fCurrentListIt != fLists->begin())
{
fIterator = (*fCurrentListIt)->begin();
fCurrentListIt--;
fIterator = (*fCurrentListIt)->end();
fIterator--;
}
if (fIterator.GetNode() == nullptr && fCurrentListIt == fLists->begin())
{
fIterator = G4FastList_iterator<OBJECT>();
return *this;
}
return *this;
}
_Self operator--(int)
{
return operator--();
}
G4bool operator==(const _Self& __x) const
{
return (fIterator == __x.fIterator && fCurrentListIt == __x.fCurrentListIt);
} // Fast check
G4bool operator!=(const _Self& __x) const
{
return !(this->operator ==(__x));
}
protected:
void HasReachedEnd()
{
if (fLists->empty() == false)
{
fIterator = (*(fLists->end()--))->end();
}
else
{
fIterator = G4FastList_iterator<OBJECT>();
}
}
};
template<class OBJECT>
typename G4ManyFastLists<OBJECT>::iterator G4ManyFastLists<OBJECT>::begin()
{
if (fAssociatedLists.empty())
{
return G4ManyFastLists_iterator<OBJECT>(G4FastList_iterator<OBJECT>(),
fAssociatedLists.end(),
&fAssociatedLists);
}
typename G4FastList<OBJECT>::iterator trackList_it;
int i = 0;
typename ManyLists::iterator it = fAssociatedLists.begin();
typename ManyLists::iterator _end = fAssociatedLists.end();
while (it != _end)
{
if (*it && (*it)->empty() == false)
{
trackList_it = (*it)->begin();
break;
}
i++;
it++;
};
if (i == fAssociatedLists.size() || it == _end)
{
return end();
}
return G4ManyFastLists_iterator<OBJECT>(trackList_it,
// fAssociatedLists.begin(),
it,
&fAssociatedLists);
}
template<class OBJECT>
typename G4ManyFastLists<OBJECT>::iterator G4ManyFastLists<OBJECT>::end()
{
if (fAssociatedLists.empty())
{
return G4ManyFastLists_iterator<OBJECT>(G4FastList_iterator<OBJECT>(),
fAssociatedLists.end(),
&fAssociatedLists);
}
return G4ManyFastLists_iterator<OBJECT>((fAssociatedLists.end()--)->end(),
fAssociatedLists.end(),
&fAssociatedLists);
}
#include "G4ManyFastLists.icc"