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 "Riostream.h"
17#include "TError.h"
18#include "TMCAutoLock.h"
19#include "TThread.h"
20
21#include <atomic>
22#include <cstdio>
23#include <thread>
24#include <vector>
25
26namespace {
27// Define mutexes per operation which modify shared data
28TMCMutex createMutex = TMCMUTEX_INITIALIZER;
29TMCMutex deleteMutex = TMCMUTEX_INITIALIZER;
30
31// A global counter to assign numbers sequentially
32std::atomic<int> global_thread_counter{0};
33
34int get_clean_thread_id()
35{
36 // This variable is unique to each thread.
37 // It initializes ONLY the first time this function is called on that thread.
38 thread_local int my_id = global_thread_counter++;
39 return my_id;
40}
41
42void threadWorker()
43{
44 // No arguments passed, but the thread can still get its 0, 1, 2 ID
45 std::cout << "Thread " << std::this_thread::get_id() << " assigned itself Custom ID: " << get_clean_thread_id()
46 << "\n";
47}
48
49} // namespace
50
51//
52// static data, methods
53//
54
56Bool_t TMCRootManager::fgDebug = false;
58
59//_____________________________________________________________________________
66
67//
68// ctors, dtor
69//
70
71//_____________________________________________________________________________
72TMCRootManager::TMCRootManager(const char *projectName, TMCRootManager::FileMode fileMode, Int_t threadRank)
73 : TMCRootManager(projectName, TMCRootManager::kTTree, fileMode, threadRank)
74{
75}
76
77//_____________________________________________________________________________
79 TMCRootManager::FileMode fileMode, Int_t threadRank)
80 : fStorageMode(storageMode)
81{
86 if (fgDebug)
87 printf("TMCRootManager::TMCRootManager %p \n", this);
88
89 // lock mutex
90 TMCAutoLock lk(&createMutex);
91
92 // Set Id
93 fId = fgCounter;
94
95 // Increment counter
96 ++fgCounter;
97
98 // singleton instance
99 if (fgInstance) {
100 Fatal("TMCRootManager", "Attempt to create two instances of singleton.");
101 return;
102 }
103
104 fgInstance = this;
105
106 // SingleThreaded or MT worker with TTree output or MT main thread
107 // open file and create a tree
108 OpenFile(projectName, fileMode, threadRank);
109
110 // unlock mutex
111 lk.unlock();
112
113 if (fgDebug)
114 printf("Done TMCRootManagerMT::TMCRootManagerMT %p \n", this);
115}
116
117#if (ROOT_VERSION_CODE >= ROOT_VERSION(6, 38, 0))
118//_____________________________________________________________________________
119TMCRootManager::TMCRootManager(std::shared_ptr<RNTParaWriter> sharedWriter)
120 : fStorageMode(TMCRootManager::kRNTuple), fParaWriter(std::move(sharedWriter))
121{
122 // Set Id
123 fId = fgCounter;
124
125 // Increment counter
126 ++fgCounter;
127
128 // singleton instance
129 if (fgInstance) {
130 Fatal("TMCRootManager", "Attempt to create two instances of singleton.");
131 return;
132 }
133
134 fgInstance = this;
135}
136#endif
137
138//_____________________________________________________________________________
140{
142
143 if (fgDebug)
144 printf("TMCRootManager::~TMCRootManager %p \n", this);
145
146 // lock mutex
147 TMCAutoLock lk(&deleteMutex);
148
149 if (fFile && !fIsClosed)
150 fFile->Close();
151 delete fFile;
152
153 --fgCounter;
154
155 // unlock mutex
156 lk.unlock();
157
158 if (fgDebug)
159 printf("Done TMCRootManager::~TMCRootManager %p \n", this);
160}
161
162//
163// privatemethods
164//
165
166//_____________________________________________________________________________
167void TMCRootManager::OpenFile(const char *projectName, FileMode fileMode, Int_t threadRank)
168{
169 TString fileName(projectName);
170 if (threadRank > 0) {
171 Int_t threadId = get_clean_thread_id();
172 fileName += "_";
173 fileName += threadId;
174 }
175 fileName += ".root";
176
177 TString treeTitle(projectName);
178 treeTitle += " tree";
179
180 switch (fileMode) {
182 fFile = new TFile(fileName);
183 if (fStorageMode == kTTree)
184 fTree = (TTree *)fFile->Get(projectName);
185 break;
186
188 if (fgDebug)
189 printf("Going to create Root file \n");
190 fFile = new TFile(fileName, "recreate");
191 if (fgDebug)
192 printf("Done: file %p \n", fFile);
193
194 if (fgDebug)
195 printf("Going to create TTree \n");
196 if (fStorageMode == kTTree)
197 fTree = new TTree(projectName, treeTitle);
198#if (ROOT_VERSION_CODE >= ROOT_VERSION(6, 38, 0))
199 if (fStorageMode == kRNTuple) {
200 fStorageName = projectName;
201 fModel = RNTupleModel::Create();
202 }
203#endif
204 if (fgDebug)
205 printf("Done: TTree %p \n", fTree);
206 ;
207 ;
208 }
209}
210
211//
212// public methods
213//
214
215//_____________________________________________________________________________
216void TMCRootManager::Register(const char *name, const char *className, void *objAddress)
217{
222
223 fFile->cd();
224 if (!fTree->GetBranch(name))
225 fTree->Branch(name, className, objAddress, 32000, 99);
226 else
227 fTree->GetBranch(name)->SetAddress(objAddress);
228}
229
230//_____________________________________________________________________________
231void TMCRootManager::Register(const char *name, const char *className, const void *objAddress)
232{
237
238 Register(name, className, const_cast<void *>(objAddress));
239}
240
241#if (ROOT_VERSION_CODE >= ROOT_VERSION(6, 38, 0))
242//_____________________________________________________________________________
243void TMCRootManager::CreateRNTuple(bool parallelMode, bool workerMode)
244{
245 if (fStorageMode == kRNTuple) {
246 if (!parallelMode) {
247 fWriter = RNTupleWriter::Append(std::move(fModel), fStorageName.c_str(), *fFile);
248 fEntry = fWriter->GetModel().CreateBareEntry();
249 for (auto nameAddress : fNameAddress) {
250 fEntry->BindRawPtr(nameAddress.first, nameAddress.second);
251 }
252 } else {
253 if (!workerMode) {
254 fParaWriter = std::shared_ptr<RNTParaWriter>(
255 RNTupleParallelWriter::Append(std::move(fModel), fStorageName.c_str(), *fFile).release());
256 } else {
257 fFillContext = fParaWriter->CreateFillContext();
258 fEntry = fFillContext->CreateEntry();
259 for (auto nameAddress : fNameAddress) {
260 fEntry->BindRawPtr(nameAddress.first, nameAddress.second);
261 }
262 }
263 }
264 }
265}
266#endif
267
268//_____________________________________________________________________________
270{
271 if (fStorageMode == kTTree) {
273 fFile->cd();
274 fTree->Fill();
275 }
276#if (ROOT_VERSION_CODE >= ROOT_VERSION(6, 38, 0))
277 else if (fStorageMode == kRNTuple) {
279 if (!fParaWriter) {
280 RNTupleFillStatus status;
281 fWriter->FillNoFlush(*fEntry, status);
282 if (status.ShouldFlushCluster()) {
283 // If we are asked to flush, first try to do as much work as possible outside of the critical section:
284 // FlushColumns() will flush column data and trigger compression, but not actually write to storage.
285 // (A framework may of course also decide to flush more often.)
286 fWriter->FlushColumns();
287 {
288 // FlushCluster() will flush data to the underlying TFile, so it requires synchronization.
289 fWriter->FlushCluster();
290 }
291 }
292 } else {
293 fFillContext->Fill(*fEntry);
294 }
295 }
296#endif
297}
298
299//_____________________________________________________________________________
301{
302 if (fStorageMode == kTTree) {
304 fFile->cd();
305 fFile->Write();
306 }
307#if (ROOT_VERSION_CODE >= ROOT_VERSION(6, 38, 0))
308 else if (fStorageMode == kRNTuple) {
310 if (fParaWriter) {
311 fEntry.reset();
312 fFillContext.reset();
313 } else {
314 fModel.reset();
315 fWriter.reset();
316 }
317 }
318#endif
319}
320
321//_____________________________________________________________________________
323{
325 if (fIsClosed) {
326 Error("Close", "The file was already closed.");
327 return;
328 }
329
330#if (ROOT_VERSION_CODE >= ROOT_VERSION(6, 38, 0))
331 if (fParaWriter) {
332 fParaWriter->CommitDataset();
333 }
334#endif
335
336 fFile->cd();
337 fFile->Close();
338 fIsClosed = true;
339}
340
341//_____________________________________________________________________________
343{
345
346 WriteAll();
347 Close();
348}
349
350//_____________________________________________________________________________
352{
355
356 fTree->GetEntry(i);
357}
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.
std::unique_ptr< RNTupleModel > fModel
void OpenFile(const char *projectName, FileMode fileMode, Int_t threadRank)
void ReadEvent(Int_t i)
static TMCThreadLocal TMCRootManager * fgInstance
FileMode
Root file mode.
std::unique_ptr< RNTupleWriter > fWriter
std::shared_ptr< RNTupleFillContext > fFillContext
static Bool_t fgDebug
std::vector< std::pair< std::string, void * > > fNameAddress
StorageMode fStorageMode
std::shared_ptr< RNTParaWriter > fParaWriter
std::string fStorageName
virtual ~TMCRootManager()
static Int_t fgCounter
static TMCRootManager * Instance()
TMCRootManager(const char *projectName, FileMode fileMode=kWrite, Int_t threadRank=-1)
std::unique_ptr< REntry > fEntry
void CreateRNTuple(bool parallelMode=false, bool workerMode=false)
void Register(const char *name, T *&obj)