Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:59:32

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 // G4ThreadLocalSingleton
0027 //
0028 // Class description:
0029 //
0030 // This class implements a thread-private "singleton". Being thread
0031 // private the singleton is not a singleton in the term, but a different
0032 // instance exists for each thread.
0033 // This class is a wrapper around the real object that we need to
0034 // make singleton.
0035 //
0036 // Limitation:
0037 //   The object that is made thread-private singleton should not
0038 //   contain any thread-local data member. Note that in general,
0039 //   if an object is to be thread-private it is unnecessary to mark
0040 //   any data-member as G4ThreadLocal.
0041 //
0042 // Performance issues:
0043 //   This class uses locks and mutexes.
0044 //
0045 // Example:
0046 //   This is the singleton pattern often found in Geant4 (sequential):
0047 //   class G4Class
0048 //   {
0049 //     private:
0050 //       static G4Class* instance;
0051 //        G4Class() { ... }
0052 //     public:
0053 //       static G4Class* GetInstance()
0054 //       {
0055 //         static G4Class theInstance;
0056 //         if ( instance == nullptr ) instance = &theInstance;
0057 //         return instance;
0058 //       }
0059 //   };
0060 //   This is transformed to the following to implement a thread-local
0061 //   singleton:
0062 //   class G4Class
0063 //   {
0064 //     private:
0065 //       static G4ThreadLocal G4Class* instance;
0066 //       G4Class() { ... }
0067 //     public:
0068 //       static G4Class* GetInstance()
0069 //       {
0070 //         if ( instance == nullptr ) instance = new G4Class;
0071 //           return instance;
0072 //       }
0073 //   };
0074 //   Note that this class also has a memory leak.
0075 //
0076 //   This class can be used as follows:
0077 //   class G4Class
0078 //   {
0079 //     friend class G4ThreadLocalSingleton<G4Class>;
0080 //     private:
0081 //       G4Class() { ... }
0082 //     public:
0083 //       static G4Class* GetInstance()
0084 //       {
0085 //         static G4ThreadLocalSingleton<G4Class> instance;
0086 //         return instance.Instance();
0087 //       }
0088 //   };
0089 //   Each thread has its own instance of G4Class.
0090 //   Deletion of G4Class instances is done at end of program.
0091 //   Note the "friend" statement.
0092 
0093 // Author: A.Dotti, 28 October 2013
0094 // --------------------------------------------------------------------
0095 #ifndef G4TLSSINGLETON_HH
0096 #define G4TLSSINGLETON_HH 1
0097 
0098 #include "G4AutoLock.hh"
0099 #include "G4Cache.hh"
0100 #include "G4Threading.hh"
0101 
0102 #include <list>
0103 #include <vector>
0104 #include <functional>
0105 
0106 // Forward declaration. See G4AutoDelete.hh
0107 //
0108 namespace G4AutoDelete
0109 {
0110   template <class T>
0111   void Register(T*);
0112 }
0113 
0114 template <class T>
0115 class G4ThreadLocalSingleton;
0116 
0117 // this explicit specialization holds all the callbacks
0118 // to explicitly invoke the auto-deletion
0119 template <>
0120 class G4ThreadLocalSingleton<void>
0121 {
0122  private:
0123   using fvector_t = std::vector<std::function<void()>>;
0124 
0125   template <class T>
0126   friend class G4ThreadLocalSingleton;
0127 
0128   static fvector_t& GetCallbacks();
0129   static G4Mutex& GetMutex();
0130 
0131  public:
0132   static void Clear();
0133 
0134   template <typename FuncT>
0135   static typename fvector_t::iterator Insert(FuncT&& _func)
0136   {
0137     G4AutoLock _lk{ GetMutex() };
0138     return GetCallbacks().emplace(GetCallbacks().end(),
0139                                   std::forward<FuncT>(_func));
0140   }
0141 };
0142 
0143 template <class T>
0144 class G4ThreadLocalSingleton : private G4Cache<T*>
0145 {
0146   friend void G4AutoDelete::Register<T>(T*);
0147 
0148  public:
0149   G4ThreadLocalSingleton();
0150   // Creates thread-local singleton manager
0151 
0152   ~G4ThreadLocalSingleton() override;
0153 
0154   G4ThreadLocalSingleton(const G4ThreadLocalSingleton&) = delete;
0155   G4ThreadLocalSingleton(G4ThreadLocalSingleton&&)      = default;
0156 
0157   G4ThreadLocalSingleton& operator=(const G4ThreadLocalSingleton&) = delete;
0158   G4ThreadLocalSingleton& operator=(G4ThreadLocalSingleton&&) = default;
0159 
0160   T* Instance() const;
0161   // Returns a pointer to a thread-private instance of T
0162 
0163  private:
0164   void Register(T* i) const;
0165 
0166   void Clear();
0167 
0168   mutable std::list<T*> instances;
0169   mutable G4Mutex listm;
0170 };
0171 
0172 //=============================================================
0173 // Inline methods implementation
0174 //=============================================================
0175 
0176 template <class T>
0177 G4ThreadLocalSingleton<T>::G4ThreadLocalSingleton()
0178   : G4Cache<T*>()
0179 {
0180   G4MUTEXINIT(listm);
0181   G4Cache<T*>::Put(nullptr);
0182   G4ThreadLocalSingleton<void>::Insert([&]() {
0183     this->Clear();
0184   });
0185 }
0186 
0187 template <class T>
0188 G4ThreadLocalSingleton<T>::~G4ThreadLocalSingleton()
0189 {
0190   Clear();
0191   G4MUTEXDESTROY(listm);
0192 }
0193 
0194 template <class T>
0195 T* G4ThreadLocalSingleton<T>::Instance() const
0196 {
0197   T* instance = G4Cache<T*>::Get();
0198   if(instance == static_cast<T*>(0))
0199   {
0200     instance = new T;
0201     G4Cache<T*>::Put(instance);
0202     Register(instance);
0203   }
0204   return instance;
0205 }
0206 
0207 template <class T>
0208 void G4ThreadLocalSingleton<T>::Register(T* i) const
0209 {
0210   G4AutoLock l(&listm);
0211   instances.push_back(i);
0212 }
0213 
0214 template <class T>
0215 void G4ThreadLocalSingleton<T>::Clear()
0216 {
0217   if(instances.empty())
0218     return;
0219   G4AutoLock l(&listm);
0220   while(!instances.empty())
0221   {
0222     T* thisinst = instances.front();
0223     instances.pop_front();
0224     delete thisinst;
0225   }
0226 }
0227 
0228 #endif