// // ******************************************************************** // * 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. * // ******************************************************************** // // $Id$ // // --------------------------------------------------------------- // GEANT 4 class header file // // Class Description: // Helper classes for Geant4 Multi-Threaded. // The classes defined in this header file provide a thread-private // cache to store, in a class instance shared among threads, // a thread-local variable V. // These are templated classes on the to-be-stored object. // // Example: // Let's assume an instance myObject of class G4Shared is sharead between // threads. Still a data member of this class needs to be thread-private. // A typical example of this being a "cache" for a local calculation. // The helper here defined can be used to guarantee thread-safe operations // on the thread-private object. // Example: // class G4Shared { // G4double sharedData; // G4Cache threadPrivate; // void foo() { // G4double priv = threadPrivate.Get(); // if ( priv < 10 ) priv += sharedData; // threadPrivate.Put( priv ); // } // }; // // Two variants of the base G4Cache exists. The first one being // G4VectorCache similar to std::vector // Example: // G4VectorCache aVect; // aVect.Push_back( 3.2 ); // aVect.Push_back( 4.1 ); // cout< aMap; // aMap[320]=1.234; // // See classes definition for details. // See testG4Cache unit test for details on usage // // History: // 21 October 2013: A. Dotti - First implementation #ifndef G4CACHE_HH #define G4CACHE_HH //Debug this code //#define g4cdebug 1 //Thread Local storage details are in this header file #include "G4CacheDetails.hh" // A templated cache to store a thread-private data of type VALTYPE. template class G4Cache { public: typedef VALTYPE value_type; // The stored type G4Cache(); // Default constructor G4Cache(const value_type& v); // Construct cache object with initial value virtual ~G4Cache(); // Default destructor inline value_type& Get() const; // Gets reference to cached value of this threads inline void Put( const value_type& val ) const; // Sets this thread cached value to val inline value_type Pop(); // Gets copy of cached value protected: const int& GetId() const { return id; } private: int id; mutable G4CacheReference theCache; static G4Mutex gMutex; static unsigned int instancesctr; static unsigned int dstrctr; inline value_type& GetCache() const { theCache.Initialize(id); return theCache.GetCache(id); } //Disable copy constructor G4Cache(const G4Cache& rhs); G4Cache& operator=(const G4Cache& rhs); }; // A vector version of the cache. Implements vector interface. // Can be used directly as a std::vector would be used. template class G4VectorCache : public G4Cache< std::vector > { public: //Some useful defintions typedef VALTYPE value_type; typedef typename std::vector vector_type; typedef typename vector_type::size_type size_type; typedef typename vector_type::iterator iterator; typedef typename vector_type::const_iterator const_iterator; G4VectorCache(); // Default constructor G4VectorCache( G4int nElems ); // Creates a vector cache of nElems elements G4VectorCache( G4int nElems , value_type* vals ); // Creates a vector cache with elements from an array virtual ~G4VectorCache(); // Default destructor // Interface with funxtionalities of similar name of std::vector inline void Push_back( const value_type& val ); inline value_type Pop_back(); inline value_type& operator[](const G4int& idx); inline iterator Begin(); inline iterator End(); inline void Clear(); inline size_type Size() { return G4Cache::Get().size(); } //Needs to be here for a VC9 compilation problem }; // a Map version of the cache. Implemetns std::map interface. // Can be used directly as a std::map would be used. // KEYTYPE being the key type and VALTYPE the value type. #include template class G4MapCache : public G4Cache > { public: //Some useful definitions typedef KEYTYPE key_type; typedef VALTYPE value_type; typedef typename std::map map_type; typedef typename map_type::size_type size_type; typedef typename map_type::iterator iterator; typedef typename map_type::const_iterator const_iterator; virtual ~G4MapCache(); // Default destructor inline G4bool Has(const key_type& k ); // Returns true if map contains element corresponding to key k // Interface with functionalities of similar name of std::map inline std::pair Insert( const key_type& k , const value_type& v ); inline iterator Begin(); inline iterator End(); inline iterator Find(const key_type& k ); inline value_type& Get(const key_type& k ); inline size_type Erase(const key_type& k ); inline value_type& operator[](const key_type& k); inline size_type Size() { return G4Cache::Get().size(); } //Needs to be here for a VC9 compilation problem }; //============================================================= // Implementation details follow //============================================================= #ifdef g4cdebug #include #include using std::cout; using std::endl; #endif #include "G4AutoLock.hh" //========= Implementation: G4Cache template G4Cache::G4Cache() { G4AutoLock l(&gMutex); id = instancesctr++; #ifdef g4cdebug cout<<"G4Cache id: "< G4Cache::G4Cache(const V& v) { G4AutoLock l(&gMutex); id = instancesctr++; Put(v); #ifdef g4cdebug cout<<"G4Cache id: "< G4Cache::~G4Cache() { //Move base calss #ifdef g4cdebug cout<<"~G4Cache id: "< V& G4Cache::Get() const { return GetCache(); } template void G4Cache::Put( const V& val ) const { GetCache() = val; } //Should here remove from cache element? template V G4Cache::Pop() { return GetCache(); } template unsigned int G4Cache::instancesctr = 0; template unsigned int G4Cache::dstrctr = 0; template G4Mutex G4Cache::gMutex = G4MUTEX_INITIALIZER; //========== Implementation: G4VectorCache template G4VectorCache::G4VectorCache() { } template G4VectorCache::~G4VectorCache() { #ifdef g4cdebug cout<<"~G4VectorCache "<::vector_type>::GetId()<<" with size: "<"; for ( size_type i = 0 ; i < Size() ; ++i ) cout< G4VectorCache::G4VectorCache(G4int nElems ) { vector_type& cc = G4Cache::Get(); cc.resize(nElems); } template G4VectorCache::G4VectorCache(G4int nElems , V* vals ) { vector_type& cc = G4Cache::Get(); cc.resize(nElems); for ( G4int idx = 0 ; idx < nElems ; ++idx ) cc[idx]=vals[idx]; } template void G4VectorCache::Push_back( const V& val ) { G4Cache::Get().push_back( val ); } template V G4VectorCache::Pop_back() { vector_type& cc = G4Cache::Get(); value_type val = cc[cc.size()-1]; cc.pop_back(); return val; } template V& G4VectorCache::operator[](const G4int& idx) { vector_type& cc = G4Cache::Get(); return cc[idx]; } template typename G4VectorCache::iterator G4VectorCache::Begin() { return G4Cache::Get().begin(); } template typename G4VectorCache::iterator G4VectorCache::End() { return G4Cache::Get().end(); } template void G4VectorCache::Clear() { G4Cache::Get().clear(); } //template //typename G4VectorCache::size_type G4VectorCache::Size() //{ // return G4Cache::Get().size(); //} //======== Implementation: G4MapType template G4MapCache::~G4MapCache() { #ifdef g4cdebug cout<<"~G4MacCache "<::GetId()<<" with size: "<"; for ( iterator it = Begin() ; it != End() ; ++it ) cout<first<<":"<second<<","; cout<<"<-"< std::pair::iterator,G4bool> G4MapCache::Insert( const K& k, const V& v ) { return G4Cache::Get().insert( std::pair(k,v) ); } //template //typename G4MapCache::size_type G4MapCache::Size() //{ // return G4Cache::Get().size(); //} template typename G4MapCache::iterator G4MapCache::Begin() { return G4Cache::Get().begin(); } template typename G4MapCache::iterator G4MapCache::End() { return G4Cache::Get().end(); } template typename G4MapCache::iterator G4MapCache::Find(const K& k ) { return G4Cache::Get().find(k); } template G4bool G4MapCache::Has(const K& k ) { return ( Find(k) != End() ); } template V& G4MapCache::Get(const K& k ) { return Find(k)->second; } template typename G4MapCache::size_type G4MapCache::Erase(const K& k ) { return G4Cache::Get().erase(k); } template V& G4MapCache::operator[](const K& k) { return (G4Cache::Get())[k]; } #endif