VMC Version 2.2
Loading...
Searching...
No Matches
TMCRootManager.cxx
Go to the documentation of this file.
1//------------------------------------------------
2// The Geant4 Virtual Monte Carlo package
3// Copyright (C) 2013 - 2018 Ivana Hrivnacova
4// All rights reserved.
5//
6// For the licensing terms see geant4_vmc/LICENSE.
7// Contact: root-vmc@cern.ch
8//-------------------------------------------------
9
14
15#include "TMCRootManager.h"
16#include "TMCAutoLock.h"
17
18#include <Riostream.h>
19#include <TError.h>
20#include <TFile.h>
21
22#include <atomic>
23#include <cstdio>
24#include <thread>
25#include <vector>
26
27namespace {
28// Define mutexes per operation which modify shared data
29TMCMutex createMutex = TMCMUTEX_INITIALIZER;
30TMCMutex deleteMutex = TMCMUTEX_INITIALIZER;
31
32// A global counter to assign numbers sequentially
33std::atomic<int> global_thread_counter{0};
34
35int get_clean_thread_id()
36{
37 // This variable is unique to each thread.
38 // It initializes ONLY the first time this function is called on that thread.
39 thread_local int my_id = ++global_thread_counter;
40 return my_id;
41}
42
43void threadWorker()
44{
45 // No arguments passed, but the thread can still get its 0, 1, 2 ID
46 std::cout << "Thread " << std::this_thread::get_id() << " assigned itself Custom ID: " << get_clean_thread_id()
47 << "\n";
48}
49
50} // namespace
51
52//
53// static data, methods
54//
55
57Bool_t TMCRootManager::fgDebug = false;
59TMCThreadLocal TMCRootManager *TMCRootManager::fgInstance = nullptr;
60
61//_____________________________________________________________________________
68
69//_____________________________________________________________________________
71{
73
74#if (ROOT_VERSION_CODE < ROOT_VERSION(6, 38, 0))
75 // Check if selected storage mode
76 if (storageMode == kRNTuple || storageMode == kRNTupleParallel) {
77 Error("SetStorageMode", "kRNTuple mode is available only with ROOT versin >= 6.38/00");
78 return;
79 }
80#endif
81
82 fgStorageMode = storageMode;
83}
84
85//_____________________________________________________________________________
87{
88 // According to the storage mode returns a prefix that can be use
89 // to define a unique file name per strorage type.
90
91 TString fileModifier = "T";
92 if (storageMode == kRNTuple) fileModifier = "R";
93 if (storageMode == kRNTupleParallel) fileModifier = "PR";
94
95 return fileModifier;
96}
97
98//
99// ctors, dtor
100//
101
102//_____________________________________________________________________________
103TMCRootManager::TMCRootManager(const char *projectName, TMCRootManager::FileMode fileMode, Int_t threadRank)
104{
109 if (fgDebug)
110 printf("TMCRootManager::TMCRootManager %p \n", this);
111
112 // lock mutex
113 TMCAutoLock lk(&createMutex);
114
115 // Set Id
116 // The Id on master and in sequential mode is always 0
117 // The Id on workers are >0.
118 fId = fgCounter;
119
120 // Increment counter
121 ++fgCounter;
122
123 // Check if an instance already exists
124 if (fgInstance != nullptr) {
125 Fatal("TMCRootManager", "Attempt to create two instances of singleton.");
126 return;
127 }
128
129 fgInstance = this;
130
131 // SingleThreaded or MT worker with TTree output or MT main thread
132 // open file and create a tree
133 OpenFile(projectName, fileMode, threadRank);
134
135 // unlock mutex
136 lk.unlock();
137
138 if (fgDebug)
139 printf("Done TMCRootManager::TMCRootManager %p \n", this);
140}
141
142//_____________________________________________________________________________
144{
146
147 if (fgDebug)
148 printf("TMCRootManager::~TMCRootManager %p \n", this);
149
150 // lock mutex
151 TMCAutoLock lk(&deleteMutex);
152
153 if (fFile && !fIsClosed) {
154 fFile->Close();
155 }
156 delete fFile;
157
158 delete fNtupleWriter;
159
160 --fgCounter;
161
162 // unlock mutex
163 lk.unlock();
164
165 if (fgDebug)
166 printf("Done TMCRootManager::~TMCRootManager %p \n", this);
167}
168
169//
170// private methods
171//
172
173//_____________________________________________________________________________
174void TMCRootManager::OpenFile(const char *projectName, FileMode fileMode, Int_t threadRank)
175{
176 if (fgDebug)
177 printf("TMCRootManager::OpenFile %p \n", this);
178
179 // add thread Id to fileName
180 TString fileName(projectName);
181 if (threadRank > 0) {
182 fileName += "_";
183 if (fileMode == kWrite) {
184 Int_t threadId = get_clean_thread_id();
185 fileName += threadId;
186 }
187 if (fileMode == kRead) {
188 fileName += threadRank;
189 }
190 }
191 fileName += ".root";
192 std::cout << "TMCRootManager::OpenFile: " << fileName << std:: endl;
193
194 TString option;
195 if (fileMode == kWrite) option = "recreate";
196 if (fileMode == kRead) option = "read";
197 Bool_t isWorker = threadRank>0;
198
199 if ( (!isWorker) || fgStorageMode != kRNTupleParallel || fileMode == kRead) {
200 // Create file unless we are on worker when parallelWrite is active
201 if (fgDebug)
202 printf("Going to open Root file \n");
203 fFile = new TFile(fileName, option);
204 if (fgDebug)
205 printf("Done: file %p \n", fFile);
206 }
207
208 if (fgStorageMode == kTTree) {
209 fNtupleWriter = new TMCTTreeWriter(projectName, fFile, threadRank>0);
210 if (fgDebug)
211 printf("Created TTreeWriter \n");
212 }
213 if (fgStorageMode == kRNTuple) {
214 fNtupleWriter = new TMCRNTupleWriter(projectName, fFile, threadRank>0);
215 if (fgDebug)
216 printf("Created RNTupleWriter \n");
217 }
219 fNtupleWriter = new TMCRNTupleParallelWriter(projectName, fFile, threadRank>0);
220 if (fgDebug)
221 printf("Created RNTupleParallelWriter \n");
222 }
223}
224
225//
226// public methods
227//
228
229//_____________________________________________________________________________
230void TMCRootManager::Register(const char *name, const char *className, void *objAddress)
231{
236
238 Error("Register", "Register methods with 'className' are available only with 'kTTree' storage mode.");
239 return;
240 }
241
242 dynamic_cast<TMCTTreeWriter*>(fNtupleWriter)->Register(name, className, objAddress);
243}
244
245//_____________________________________________________________________________
246void TMCRootManager::Register(const char *name, const char *className, const void *objAddress)
247{
252
253 Register(name, className, const_cast<void *>(objAddress));
254}
255
256//_____________________________________________________________________________
258{
261
262 fNtupleWriter->CreateRNTuple();
263}
264
265//_____________________________________________________________________________
267{
268 fNtupleWriter->Fill();
269}
270
271//_____________________________________________________________________________
273{
274 fNtupleWriter->WriteAll();
275}
276
277//_____________________________________________________________________________
279{
281
282 if ((fId > 0) && (fgStorageMode == kRNTupleParallel)) {
283 // Do nothing if in parallel mode on worker
284 return;
285 }
286
287 if (fIsClosed) {
288 Error("Close", "The file was already closed.");
289 return;
290 }
291
292 fNtupleWriter->Close();
293 fFile->cd();
294 fFile->Close();
295 fIsClosed = true;
296}
297
298//_____________________________________________________________________________
300{
302
303 WriteAll();
304 Close();
305}
306
307//_____________________________________________________________________________
309{
312
313 fNtupleWriter->ReadEvent(i);
314}
std::mutex TMCMutex
TMCTemplateAutoLock< TMCMutex > TMCAutoLock
#define TMCMUTEX_INITIALIZER
Definition of the TMCRootManager class.
The Root IO manager for VMC examples for both sequential and multi-threaded applications.
TMCVNtupleWriter * fNtupleWriter
void OpenFile(const char *projectName, FileMode fileMode, Int_t threadRank)
void ReadEvent(Int_t i)
static TMCThreadLocal TMCRootManager * fgInstance
FileMode
Root file mode.
static StorageMode fgStorageMode
static Bool_t fgDebug
TString GetFileModifier() const
virtual ~TMCRootManager()
static Int_t fgCounter
static TMCRootManager * Instance()
TMCRootManager(const char *projectName, FileMode fileMode=kWrite, Int_t threadRank=-1)
static void SetStorageMode(StorageMode mode)
void Register(const char *name, T *&obj)