Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-17 08:30:48

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