Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGeoMCBranchArrayContainer.cxx
Go to the documentation of this file.
1 // @(#)root/vmc:$Id$
2 // Authors: Benedikt Volkel 07/03/2019
3 
4 /*************************************************************************
5  * Copyright (C) 2019, Rene Brun and Fons Rademakers. *
6  * Copyright (C) 2019, ALICE Experiment at CERN. *
7  * All rights reserved. *
8  * *
9  * For the licensing terms see $ROOTSYS/LICENSE. *
10  * For the list of contributors see $ROOTSYS/README/CREDITS. *
11  *************************************************************************/
12 
13 /** \class TGeoMCBranchArrayContainer
14  \ingroup vmc
15 
16 Storing and re-using geometry states of the TGeoManager in use by storing
17 them as TGeoBranchArrays.
18 
19 After having initialized a navigator using a stored state, it can be freed
20 to be used again for storing another geometry state. This makes it easy to
21 handle many events with many stored geometry states and the memory used is
22 kept as small as possible.
23 */
24 
26 #include "TGeoManager.h"
27 #include "TError.h"
28 
29 void TGeoMCBranchArrayContainer::Initialize(UInt_t maxLevels, UInt_t size)
30 {
31  fMaxLevels = maxLevels;
32  if (fIsInitialized) {
33  ResetCache();
34  }
35  ExtendCache(size);
36  fIsInitialized = kTRUE;
37 }
38 
39 void TGeoMCBranchArrayContainer::InitializeFromGeoManager(TGeoManager *man, UInt_t size)
40 {
41  Initialize(man->GetMaxLevels(), size);
42 }
43 
44 void TGeoMCBranchArrayContainer::ResetCache()
45 {
46  fCache.clear();
47  fFreeIndices.clear();
48  fIsInitialized = kFALSE;
49 }
50 
51 TGeoBranchArray *TGeoMCBranchArrayContainer::GetNewGeoState(UInt_t &userIndex)
52 {
53  if (fFreeIndices.empty()) {
54  ExtendCache(2 * fCache.size());
55  }
56  // Get index from the back
57  UInt_t internalIndex = fFreeIndices.back();
58  fFreeIndices.pop_back();
59  // indices seen by the user are +1
60  userIndex = internalIndex + 1;
61  fCache[internalIndex]->SetUniqueID(userIndex);
62  return fCache[internalIndex].get();
63 }
64 
65 const TGeoBranchArray *TGeoMCBranchArrayContainer::GetGeoState(UInt_t userIndex)
66 {
67  if (userIndex == 0) {
68  return nullptr;
69  }
70  if (userIndex > fCache.size()) {
71  ::Fatal("TGeoMCBranchArrayContainer::GetGeoState",
72  "ID %u is not an index referring to TGeoBranchArray "
73  "managed by this TGeoMCBranchArrayContainer",
74  userIndex);
75  }
76  if (fCache[userIndex - 1]->GetUniqueID() == 0) {
77  ::Fatal("TGeoMCBranchArrayContainer::GetGeoState", "Passed index %u refers to an empty/unused geo state",
78  userIndex);
79  }
80  return fCache[userIndex - 1].get();
81 }
82 
83 void TGeoMCBranchArrayContainer::FreeGeoState(UInt_t userIndex)
84 {
85  if (userIndex > fCache.size() || userIndex == 0) {
86  return;
87  }
88  // Unlock this index so it is free for later use. No need to delete since TGeoBranchArray can be re-used
89  if (fCache[userIndex - 1]->GetUniqueID() > 0) {
90  fFreeIndices.push_back(userIndex - 1);
91  fCache[userIndex - 1]->SetUniqueID(0);
92  }
93 }
94 
95 void TGeoMCBranchArrayContainer::FreeGeoState(const TGeoBranchArray *geoState)
96 {
97  if (geoState) {
98  FreeGeoState(geoState->GetUniqueID());
99  }
100 }
101 
102 void TGeoMCBranchArrayContainer::FreeGeoStates()
103 {
104  // Start counting at 1 since that is the index seen by the user which is assumed by
105  // TGeoMCBranchArrayContainer::FreeGeoState(UInt_t userIndex)
106  for (UInt_t i = 0; i < fCache.size(); i++) {
107  FreeGeoState(i + 1);
108  }
109 }
110 
111 void TGeoMCBranchArrayContainer::ExtendCache(UInt_t targetSize)
112 {
113  if (targetSize <= fCache.size()) {
114  targetSize = 2 * fCache.size();
115  }
116  fFreeIndices.reserve(targetSize);
117  fCache.reserve(targetSize);
118  for (UInt_t i = fCache.size(); i < targetSize; i++) {
119  fCache.emplace_back(TGeoBranchArray::MakeInstance(fMaxLevels));
120  fCache.back()->SetUniqueID(0);
121  fFreeIndices.push_back(i);
122  }
123 }