DepMan.cxx
Go to the documentation of this file.
1 #include "CAFAna/Core/DepMan.h"
2 
3 #include "CAFAna/Core/UtilsExt.h" // DemangledTypeName()
4 
5 #include <cassert>
6 #include <cstdlib>
7 #include <iostream>
8 
9 // The idea is to keep a tree of what objects are copy-constructed from which
10 // others. Any object whose source is not constructed yet should skip
11 // construction, and this DependencyManager will later fill them in once the
12 // source object becomes available. Since the dependencies form a tree, and
13 // ultimately all objects should be constructed, we expect to be able to fulfil
14 // all dependencies before user code starts running.
15 //
16 // The one tricky spot is when B is deleted from A <- B <- C before C has been
17 // constructed. We simplify the graph to A <- C and wait.
18 
19 namespace
20 {
21  /// STL semantics for erase are annoying, make an infallible one
22  template<class T, class U> void maybe_erase(T& collection, const U& key)
23  {
24  auto it = collection.find(key);
25  if(it != collection.end()) collection.erase(it);
26  }
27 
28  // Likewise
29  template<class T, class U> U*
30  maybe_find(std::unordered_map<const T*, U>& col, const T* key)
31  {
32  auto it = col.find(key);
33  if(it == col.end()) return 0;
34  return &it->second;
35  }
36 
37  // The static for the DepMan singleton might be destroyed before various
38  // classes which might then try to access it in their own destructors. Make
39  // everything a no-op during shutdown.
40  bool gDuringShutdown = false;
41  void DepManAtExit(){gDuringShutdown = true;}
42  const struct RegisterDepManAtExit
43  {
44  RegisterDepManAtExit(){atexit(DepManAtExit);}
45  } gRegisterDepManAtExit;
46 }
47 
48 namespace ana
49 {
50  // --------------------------------------------------------------------------
51  template<class T> DepMan<T>& DepMan<T>::Instance()
52  {
53  // Avoid static order problems for the manager itself
54  static DepMan<T> dm;
55  return dm;
56  }
57 
58  // --------------------------------------------------------------------------
59  template<class T> void DepMan<T>::Print()
60  {
61  std::cout << "DepMan for "<< DemangledTypeName<T>() << " :\n";
62  if(gDuringShutdown){
63  std::cout << " Unable to print during shutdown" << std::endl;
64  }
65  else{
66  std::cout << " assisted construction of " << fNOps << " objects. "
67  << fNodes.size() << " still awaiting construction."
68  << std::endl;
69  }
70  }
71 
72  // --------------------------------------------------------------------------
73  template<class T> void DepMan<T>::RegisterConstruction(T* x)
74  {
75  if(fDisabled || gDuringShutdown) return;
76 
77  ParentKids* xnode = maybe_find(fNodes, x);
78  if(!xnode) return; // No record of us, nothing to do
79 
80  std::unordered_set<T*> kids = xnode->kids;
81 
82  // We have been constructed, so parent doesn't need to remember us
83  // anymore
84  ParentKids* pnode = maybe_find(fNodes, xnode->parent);
85  if(pnode) maybe_erase(pnode->kids, x);
86  // Nor do we need to remember anything about this node anymore
87  maybe_erase(fNodes, x);
88 
89  // Assign into all the kids that were depending on us. They in turn will
90  // register their construction and so recurse into any grandkids.
91  for(T* kid: kids) *kid = *x;
92 
93  fNOps += kids.size();
94  }
95 
96  // --------------------------------------------------------------------------
97  template<class T> void DepMan<T>::RegisterDestruction(T* x)
98  {
99  if(fDisabled || gDuringShutdown) return;
100 
101  ParentKids* xnode = maybe_find(fNodes, x);
102  if(!xnode) return; // No record of us, nothing to do
103 
104  // Make the parent forget about us
105  ParentKids* pnode = maybe_find(fNodes, xnode->parent);
106  if(pnode) pnode->kids.erase(x);
107 
108  // Kids need to forget about us, but get hooked up to their grandparent
109  // instead.
110  for(T* kid: xnode->kids){
111  ParentKids* knode = maybe_find(fNodes, kid);
112 
113  if(knode) knode->parent = xnode->parent;
114  if(pnode) pnode->kids.insert(kid);
115  }
116 
117  fNodes.erase(x); // And finally forget this node in particular
118  }
119 
120  // --------------------------------------------------------------------------
121  template<class T> void DepMan<T>::
122  RegisterDependency(const T* parent, T* child)
123  {
124  if(fDisabled || gDuringShutdown) return;
125 
126  fNodes[child].parent = parent;
127  fNodes[parent].kids.insert(child);
128  }
129 
130  // --------------------------------------------------------------------------
131  template<class T> void DepMan<T>::Disable()
132  {
133  if(!gDuringShutdown) fDisabled = true;
134  }
135 
136  // --------------------------------------------------------------------------
137  template<class T> void DepMan<T>::Enable()
138  {
139  if(!gDuringShutdown) fDisabled = false;
140  }
141 }
142 
143 // ----------------------------------------------------------------------------
144 // ----------------------------------------------------------------------------
145 // ----------------------------------------------------------------------------
146 
147 // We have to instantiate all the variants we expect
148 
149 #include "CAFAna/Core/Cut.h"
150 #include "CAFAna/Core/Var.h"
151 #include "CAFAna/Core/Binning.h"
152 
153 namespace ana
154 {
155  template class DepMan<Cut>;
156  template class DepMan<SpillCut>;
157  template class DepMan<NuTruthCut>;
158 
159  template class DepMan<Var>;
160  template class DepMan<SpillVar>;
161  template class DepMan<NuTruthVar>;
162 
163  template class DepMan<Binning>;
164 }
Cuts and Vars for the 2020 FD DiF Study.
Definition: vars.h:6
set< int >::iterator it
Deep magic to fix static initialization order. Here Be Dragons!
Definition: DepMan.h:12
Int_t col[ntarg]
Definition: Style.C:29
const T * parent
Definition: DepMan.h:32
OStream cout
Definition: OStream.cxx:6
void Print(std::string prefix, std::string name, std::string suffix="")
Definition: nue_pid_effs.C:68
std::unordered_set< T * > kids
Definition: DepMan.h:32
double T
Definition: Xdiff_gwt.C:5