Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:58:21

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 // G4GeomSplitter
0027 //
0028 // Class description:
0029 //
0030 // Utility template class for splitting of RW data for thread-safety from
0031 // classes: G4LogicalVolume, G4Region, G4VPhysicalVolume, G4PolyconeSide
0032 // G4PolyhedraSide, G4PVReplica. 
0033 
0034 // Author: X.Dong - Initial version from automatic MT conversion, 01.25.09.
0035 // ------------------------------------------------------------------------
0036 #ifndef G4GEOMSPLITTER_HH
0037 #define G4GEOMSPLITTER_HH
0038 
0039 #include "globals.hh"
0040 #include "geomwdefs.hh"
0041 #include "G4AutoLock.hh"
0042 
0043 template <class T>  // T is the private data from the object to be split
0044 class G4GeomSplitter
0045 {
0046   public:
0047 
0048     G4GeomSplitter()
0049       :  sharedOffset(nullptr)
0050     {
0051       G4MUTEXINIT(mutex);
0052     }
0053 
0054     T* Reallocate(G4int size)
0055     {
0056        totalspace = size;
0057        return (T *) std::realloc(offset, totalspace * sizeof(T));
0058     }
0059 
0060     G4int CreateSubInstance()
0061       // Invoked by the master or work thread to create a new subinstance
0062       // whenever a new split class instance is created.
0063     {
0064       G4AutoLock l(&mutex);
0065       ++totalobj;
0066       if (totalobj > totalspace)
0067       {
0068         offset = Reallocate(totalspace+512);
0069         if (offset == nullptr)
0070         {
0071            G4Exception("G4GeomSPlitter::CreateSubInstance()",
0072                        "OutOfMemory", FatalException, "Cannot malloc space!");
0073         }
0074         sharedOffset = offset;
0075       }
0076       return (totalobj - 1);
0077     }
0078 
0079     void CopyMasterContents()
0080     {
0081       G4AutoLock l(&mutex);
0082       std::memcpy(offset, sharedOffset, totalspace * sizeof(T));
0083     }
0084   
0085     void SlaveCopySubInstanceArray()
0086       // Invoked by each worker thread to copy all the subinstance array
0087       // from the master thread.
0088     {
0089       G4AutoLock l(&mutex);
0090       if (offset != nullptr)  { return; }
0091       offset = Reallocate(totalspace);
0092       if (offset == nullptr)
0093       {
0094         G4Exception("G4GeomSplitter::SlaveCopySubInstanceArray()",
0095                     "OutOfMemory", FatalException, "Cannot malloc space!");
0096       }
0097       l.unlock();
0098       CopyMasterContents();
0099     }
0100 
0101     void SlaveInitializeSubInstance()
0102       // Invoked by each worker thread to create the subinstance array and
0103       // initialize each subinstance using a particular method defined by
0104       // the subclass.
0105     {
0106       G4AutoLock l(&mutex);
0107       if (offset != nullptr)  { return; }
0108       offset = Reallocate(totalspace);
0109 
0110       if (offset == nullptr)
0111       {
0112         G4Exception("G4GeomSplitter::SlaveInitializeSubInstance()",
0113                     "OutOfMemory", FatalException, "Cannot malloc space!");
0114       }
0115 
0116       for (G4int i=0 ; i<totalspace; ++i)
0117       {
0118         offset[i].initialize();
0119       }
0120     }
0121 
0122     void SlaveReCopySubInstanceArray()
0123       // Invoked by each worker thread at start of a run (2nd or later)
0124       // to copy again all the subinstance array from the master thread.
0125       // To cope with user's changes in Geometry - e.g. change of material
0126       // in a volume
0127     {
0128       if (offset == nullptr)
0129       {
0130         SlaveInitializeSubInstance();
0131         G4Exception("G4GeomSPlitter::SlaveReCopySubInstance()",
0132                     "MissingInitialisation", JustWarning,
0133                     "Must be called after Initialisation or first Copy.");
0134       }
0135       CopyMasterContents();
0136     }
0137   
0138     void FreeSlave()
0139       // Invoked by all threads to free the subinstance array.
0140     {
0141       if (offset == nullptr)  { return; }
0142       std::free( offset );
0143       offset = nullptr;
0144     }
0145 
0146     // Extension - to allow sharing of workspaces
0147   
0148     T* GetOffset() { return offset; }
0149   
0150     void UseWorkArea( T* newOffset )
0151       // Use recycled work area - which was created previously
0152     {
0153       if( (offset!=nullptr) && (offset!=newOffset) )
0154       {
0155          G4Exception("G4GeomSplitter::UseWorkspace()", 
0156                      "TwoWorkspaces", FatalException,
0157                      "Thread already has workspace - cannot use another.");
0158       }
0159       offset= newOffset;
0160     }
0161 
0162     T* FreeWorkArea()
0163       // Detach this thread from this Location.
0164       // The object which calls this method is responsible for it.
0165     {
0166       T* offsetRet = offset;
0167       offset = nullptr;
0168       return offsetRet;
0169     }
0170 
0171   public:
0172 
0173     G4GEOM_DLL static G4ThreadLocal T* offset;
0174 
0175   private:
0176 
0177     G4int totalobj{0};
0178     G4int totalspace{0};
0179     T* sharedOffset;
0180     G4Mutex mutex;
0181 };
0182 
0183 template <typename T> G4ThreadLocal T* G4GeomSplitter<T>::offset = nullptr;
0184 
0185 #endif