Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4VUPLSplitter.hh
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27//
28//
29// ------------------------------------------------------------
30//
31// GEANT 4 class header file
32//
33// ---------------- G4UPLSplitter ----------------
34//
35// Utility template class for splitting RW data for thread-safety from
36// classes: G4UserPhysicsList, G4VPhysicsConstructor and G4CModularPhsyicsList
37//
38// ------------------------------------------------------------
39// History:
40// 01.25.2009 Xin Dong: First implementation from automatic MT conversion.
41// ------------------------------------------------------------
42#ifndef G4VUPLSPLITTER_HH
43#define G4VUPLSPLITTER_HH
44
45#include <stdlib.h>
46
47#include "G4AutoLock.hh"
48#include "globals.hh"
49#include "rundefs.hh"
50//
51// This class implements the split-mechanism for shared objects.
52// Let's see how it works.
53// In the split-class we have an instance of this class and an G4int instanceID
54// Every time, in the master thread a new instance of the split-class
55// is created the constructor calls:
56// instanceID = g4vuplsplitter.CreateInstance();
57// This creates in memory an "array", pointed by "sharedOffset" of capacity
58// "totalspace" The array contains "totalobj" (<=totalspace) instances (i.e. the
59// array has un-initialized spaces) Note that also the TLS variables "offset"
60// and "workertotalspace" have also the same stuff When a worker thread is
61// started we can call g4vuplsplitter.NewSubInstances() This will simply
62// allocate enough space in the TLS space "offset" and call T::initialize() onto
63// the new created methods. Alternatively one can call, when the worker thread
64// start, g4vuplsplitter.workerCopySubInstanceArray() That will copy the content
65// of master thread "array" into the TLS one
66
67// To see this stuff in action see:
68// G4VUserPhysicsList class and G4WorkerThread classes.
69
70template <class T> // T is the private data from the object to be split
72{
73 public:
75 : totalobj(0)
76 , totalspace(0)
77 , sharedOffset(0)
78 {
80 }
81
83 // Invoked by the master thread to create a new subinstance
84 // whenever a new split class instance is created.
85 // This is called by constructor of shared classes, thus only master thread
86 // calls this
87 {
88 G4AutoLock l(&mutex);
89 // One more instance
90 totalobj++;
91 // If the number of objects is larger than the available spaces,
92 // a re-allocation is needed
93 if(totalobj > workertotalspace)
94 {
95 l.unlock();
97 l.lock();
98 }
99 // Since this is called by Master thread, we can remember this
100 totalspace = workertotalspace;
101 sharedOffset = offset;
102 return (totalobj - 1);
103 }
104
106 // Invoked by each worker thread to grow the subinstance array and
107 // initialize each new subinstance using a particular method defined
108 // by the subclass.
109 {
110 G4AutoLock l(&mutex);
111 if(workertotalspace >= totalobj)
112 {
113 return;
114 }
115 // Remember current large size
116 G4int originaltotalspace = workertotalspace;
117 // Increase its size by some value (purely arbitrary)
118 workertotalspace = totalobj + 512;
119 // Now re-allocate new space
120 offset = (T*) realloc(offset, workertotalspace * sizeof(T));
121 if(offset == 0)
122 {
123 G4Exception("G4VUPLSplitter::NewSubInstances()", "OutOfMemory",
124 FatalException, "Cannot malloc space!");
125 return;
126 }
127 // The newly created objects need to be initialized
128 for(G4int i = originaltotalspace; i < workertotalspace; i++)
129 {
130 offset[i].initialize();
131 }
132 }
133
135 // Invoked by all threads to free the subinstance array.
136 {
137 if(!offset)
138 {
139 return;
140 }
141 free(offset);
142 offset = 0;
143 }
144
145 T* GetOffset() { return offset; }
146
147 void UseWorkArea(T* newOffset)
148 {
149 // Use recycled work area - which was created previously
150 if(offset && offset != newOffset)
151 {
152 G4Exception("G4VUPLSplitter::UseWorkspace()", "TwoWorkspaces",
154 "Thread already has workspace - cannot use another.");
155 }
156 offset = newOffset;
157 // totalobj= numObjects;
158 // totalspace= numSpace;
159 }
160
161 T* FreeWorkArea() // G4int* numObjects, G4int* numSpace)
162 {
163 // Detach this thread from this Location
164 // The object which calls this method is responsible for it.
165 //
166 T* offsetRet = offset;
167
168 offset = 0;
169
170 return offsetRet;
171 }
172
174 // Invoked by each worker thread to copy all subinstances array from
175 // the master thread
176 {
177 if(offset)
178 return;
179 // Since this is called by worker threds, totalspace is some valid number >
180 // 0 Remember totalspace is the number of availabel slots from master. We
181 // are sure that it has valid data
182 G4AutoLock l(&mutex);
183 offset = (T*) realloc(offset, totalspace * sizeof(T));
184 if(offset == 0)
185 {
186 G4Exception("G4VUPLSplitter::WorkerCopySubInstanceArray()", "OutOfMemory",
187 FatalException, "Cannot malloc space!");
188 return;
189 }
190 // Now just copy from master thread (sharedOffset)
191 memcpy(offset, sharedOffset, totalspace * sizeof(T));
192 }
193
194 public:
196 // number of slots
198 T* offset; // Pointer to first instance of an array
199
200 private:
201 G4int totalobj; // Total number of instances from master thread
202 G4int totalspace; // Available number of "slots"
203 T* sharedOffset;
205};
206
207template <typename T>
209template <typename T>
211
212#endif
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::mutex G4Mutex
Definition: G4Threading.hh:81
#define G4MUTEXINIT(mutex)
Definition: G4Threading.hh:87
int G4int
Definition: G4Types.hh:85
void WorkerCopySubInstanceArray()
G4RUN_DLL G4ThreadLocalStatic G4int workertotalspace
G4RUN_DLL G4ThreadLocalStatic T * offset
G4int CreateSubInstance()
void UseWorkArea(T *newOffset)
#define G4RUN_DLL
Definition: rundefs.hh:47
#define G4ThreadLocalStatic
Definition: tls.hh:76
#define G4ThreadLocal
Definition: tls.hh:77