Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DParsedEvent.h
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DParsedEvent.h
4 // Created: Mon Mar 28 11:07:41 EDT 2016
5 // Creator: davidl (on Darwin harriet.jlab.org 13.4.0 i386)
6 //
7 
8 #ifndef _DParsedEvent_
9 #define _DParsedEvent_
10 
11 #include <string>
12 #include <map>
13 using std::string;
14 using std::map;
15 
16 #include <JANA/jerror.h>
17 #include <JANA/JObject.h>
18 #include <JANA/JEventLoop.h>
19 using namespace jana;
20 
21 #include <DANA/DStatusBits.h>
22 #include <DAQ/daq_param_type.h>
23 #include <DAQ/DModuleType.h>
24 
25 
26 #include <DAQ/Df250Config.h>
27 #include <DAQ/Df250PulseIntegral.h>
29 #include <DAQ/Df250WindowSum.h>
30 #include <DAQ/Df250PulseRawData.h>
31 #include <DAQ/Df250TriggerTime.h>
32 #include <DAQ/Df250PulseTime.h>
33 #include <DAQ/Df250PulsePedestal.h>
34 #include <DAQ/Df250PulseData.h>
35 #include <DAQ/Df250WindowRawData.h>
36 #include <DAQ/Df125Config.h>
37 #include <DAQ/Df125TriggerTime.h>
38 #include <DAQ/Df125PulseIntegral.h>
39 #include <DAQ/Df125PulseTime.h>
40 #include <DAQ/Df125PulsePedestal.h>
41 #include <DAQ/Df125PulseRawData.h>
42 #include <DAQ/Df125WindowRawData.h>
43 #include <DAQ/Df125CDCPulse.h>
44 #include <DAQ/Df125FDCPulse.h>
45 #include <DAQ/DF1TDCConfig.h>
46 #include <DAQ/DF1TDCHit.h>
47 #include <DAQ/DF1TDCTriggerTime.h>
48 #include <DAQ/DCAEN1290TDCConfig.h>
49 #include <DAQ/DCAEN1290TDCHit.h>
50 #include <DAQ/DCODAEventInfo.h>
51 #include <DAQ/DCODAControlEvent.h>
52 #include <DAQ/DCODAROCInfo.h>
53 #include <DAQ/Df250Scaler.h>
54 #include <DAQ/DL1Info.h>
55 #include <DAQ/DEPICSvalue.h>
56 #include <DAQ/DEventTag.h>
57 #include <DAQ/Df250BORConfig.h>
58 #include <DAQ/Df125BORConfig.h>
59 #include <DAQ/DF1TDCBORConfig.h>
61 #include <DAQ/DTSGBORConfig.h>
62 #include <DAQ/DDIRCTriggerTime.h>
63 #include <DAQ/DDIRCTDCHit.h>
64 #include <DAQ/DDIRCADCHit.h>
65 #include <DAQ/DBORptrs.h>
66 #include <PID/DVertex.h>
67 #include <PID/DEventRFBunch.h>
68 
69 // Here is some C++ macro script-fu. For each type of class the DParsedEvent
70 // can hold, we want to have a vector of pointers to that type of object.
71 // There's also a number of other things we need to do for each of these types
72 // but don't want to have to write the entire list out multiple times. The
73 // "MyTypes" macro below defines all of the types and then is used multiple
74 // times in the DParsedEvent class. It would be nice if we could also generate
75 // the above #includes using this trick but alas, the C++ language
76 // prohibits using #includes in macros so it's not possible.
77 #define MyTypes(X) \
78  X(Df250Config) \
79  X(Df250PulseIntegral) \
80  X(Df250StreamingRawData) \
81  X(Df250WindowSum) \
82  X(Df250PulseRawData) \
83  X(Df250TriggerTime) \
84  X(Df250PulseTime) \
85  X(Df250PulsePedestal) \
86  X(Df250PulseData) \
87  X(Df250WindowRawData) \
88  X(Df125Config) \
89  X(Df125TriggerTime) \
90  X(Df125PulseIntegral) \
91  X(Df125PulseTime) \
92  X(Df125PulsePedestal) \
93  X(Df125PulseRawData) \
94  X(Df125WindowRawData) \
95  X(Df125CDCPulse) \
96  X(Df125FDCPulse) \
97  X(DF1TDCConfig) \
98  X(DF1TDCHit) \
99  X(DF1TDCTriggerTime) \
100  X(DCAEN1290TDCConfig) \
101  X(DCAEN1290TDCHit) \
102  X(DCODAEventInfo) \
103  X(DCODAControlEvent) \
104  X(DCODAROCInfo) \
105  X(DL1Info) \
106  X(Df250Scaler) \
107  X(DEPICSvalue) \
108  X(DEventTag) \
109  X(DDIRCTriggerTime) \
110  X(DDIRCTDCHit) \
111  X(DDIRCADCHit)
112 
113 // These data types are optionally stored in EVIO files from specialized process
114 // (e.g. calibration skims) and could be provided by standard analysis factories
115 // Therefore, we deliver these data types ONLY IF they exist in the file
116 #define MyDerivedTypes(X) \
117  X(DVertex) \
118  X(DEventRFBunch)
119 
120 // It turns out that since we use object pools and in-place constructors, a
121 // memory leak occurs for things like the samples vector in the Window Raw
122 // data classes. This is because the in-place constructor re-initializes
123 // the samples vector's underlying data pointer to NULL without freeing
124 // the memory it points to. The easiest way around this is to just not use
125 // a pool for these data types so the destructor is properly called. This
126 // means a slight drop in efficiency, but only for data containing WRD which
127 // is going to be slow anyway.
128 #define MyNoPoolTypes(X) \
129  X(Df250WindowRawData) \
130  X(Df125WindowRawData)
131 
133  public:
134 
135  atomic<bool> in_use;
136  uint64_t Nrecycled; // Incremented in DEVIOWorkerThread::MakeEvents()
137  uint64_t MAX_RECYCLES;
139 
140  uint32_t buff_len; // original EVIO buffer that may contian many events
141  uint64_t istreamorder;
142  uint64_t run_number;
143  uint64_t event_number;
145  bool sync_flag;
146 
148 
149  // For each type defined in "MyTypes" above, define a vector of
150  // pointers to it with a name made by prepending a "v" to the classname
151  // The following expands to things like e.g.
152  //
153  // vector<Df250Config*> vDf250Config;
154  //
155  #define makevector(A) vector<A*> v##A;
159 
160  // DParsedEvent objects are recycled to save malloc/delete cycles. Do the
161  // same for the objects they provide by creating a pool vector for each
162  // object type. No need for locks here since this will only ever be accessed
163  // by the same worker thread.
164  #define makepoolvector(A) vector<A*> v##A##_pool;
167 
168  // Method to return all objects in vectors to their respective pools and
169  // clear the vectors to set up for processing the next event. Vectors
170  // with BOR types are just cleared.
171  // This is called from DEVIOWorkerThread::MakeEvents
172  #define returntopool(A) if(!v##A.empty()){ v##A##_pool.insert(v##A##_pool.end(), v##A.begin(), v##A.end()); }
173  #define clearvectors(A) v##A.clear();
174  #define deletepool(A) for(auto p : v##A##_pool) delete p;
175  #define clearpoolvectors(A) v##A##_pool.clear();
176  void Clear(void){
184  }
185 
186  // Method to delete all objects in all vectors and all pools. This should
187  // usually only be called from the DParsedEvent destructor
188  #define deletevector(A) for(auto p : v##A ) delete p;
189  void Delete(void){
199  }
200 
201  // This is used to occasionally delete extra pool objects to reduce the
202  // average memory use. It is called from DEVIOWorkerThread::MakeEvents
203  // every MAX_RECYCLES events processed by this DParsedEvent object.
204  void Prune(void){
209  }
210 
211  // Define a class that has pointers to factories for each data type.
212  // One of these is instantiated for each JEventLoop encountered.
213  // See comments below for CopyToFactories for details.
214  #define makefactoryptr(A) JFactory<A> *fac_##A;
215  #define copyfactoryptr(A) fac_##A = (JFactory<A>*)loop->GetFactory(#A);
217  public:
218  JEventLoop *loop;
222 
223  DFactoryPointers():loop(NULL){}
225 
226  void Init(JEventLoop *loop){
227  this->loop = loop;
231  }
232  };
233 
234  // Copy objects to factories. For efficiency, we keep an object that
235  // holds the relevant factory pointers for each JEventLoop we encounter.
236  // This avoids having to look up the factory pointer for each data type
237  // for every event. Note that only one processing thread at a time will
238  // ever call this method for this DParsedEvent object so we don't need
239  // to lock access to the factory_pointers map.
240  #define copytofactory(A) facptrs.fac_##A->CopyTo(v##A);
241  #define copybortofactory(A) facptrs.fac_##A->CopyTo(borptrs->v##A);
242  #define setevntcalled(A) facptrs.fac_##A->Set_evnt_called();
243  #define keepownership(A) facptrs.fac_##A->SetFactoryFlag(JFactory_base::NOT_OBJECT_OWNER);
244  #define copytofactorynonempty(A) if(!v##A.empty()) facptrs.fac_##A->CopyTo(v##A);
245  #define setevntcallednonempty(A) if(!v##A.empty()) facptrs.fac_##A->Set_evnt_called();
246  #define keepownershipnonempty(A) if(!v##A.empty()) facptrs.fac_##A->SetFactoryFlag(JFactory_base::NOT_OBJECT_OWNER);
247  void CopyToFactories(JEventLoop *loop){
248  // Get DFactoryPointers for this JEventLoop, creating new one if necessary
249  DFactoryPointers &facptrs = factory_pointers[loop];
250  if(facptrs.loop == NULL) facptrs.Init(loop);
251 
252  // Copy all data vectors to appropriate factories
259  if(borptrs){
263  }
264  copied_to_factories=true;
265  }
266 
267  // Method to check class name against each classname in MyTypes returning
268  // true if found and false if not.
269  #define checkclassname(A) if(classname==#A) return true;
270  bool IsParsedDataType(string &classname)const {
274  return false;
275  }
276 
277  // Method to check class name against each classname in MyTypes returning
278  // true only if this is a class that is usually produced by some
279  // ther factor, but we have some data of this type. Otherwise returns false
280  #define checknonemptyderivedclassname(A) if((classname==#A)&&(!v##A.empty())) return true;
281  bool IsNonEmptyDerivedDataType(string &classname)const {
283  return false;
284  }
285 
286  // Get name of all classes we provide. Default is to provide only
287  // those with non-empty vector unless "include_all" is set true
288  #define addclassname(A) if(include_all || !v##A.empty())classnames.push_back(#A);
289  void GetParsedDataTypes(vector<string> &classnames, bool include_all=false) const {
293  }
294 
295  // The following is pretty complicated to understand. What it does is
296  // create a templated method for each data type that is used to
297  // replace the use of "new" to allocate an object of that type.
298  // What makes it complicated is the use of C++11 variadic functions
299  // to allow passing in (and through) variable length argument lists.
300  // This is needed since each type's constructor takes a different
301  // set of arguments and we don't want to have to encode all of that
302  // here.
303  //
304  // For each data type, a method called NEW_XXX is defined that looks
305  // to see if an object already exists in the corresponding pool vector.
306  // If so, it returns a pointer to it after doing an in-place constructor
307  // call with the given arguments. If no objects are available in the
308  // pool, then a new one is created in the normal way with the given
309  // arguments.
310  //
311  // This will also automatically add the created/recycled object to
312  // the appropriate vXXX vector as part of the current event. It
313  // returns of pointer to the object so that it can be accessed by the
314  // caller if needed.
315  //
316  // This will provide a method that looks something like this:
317  //
318  // Df250TriggerTime* NEW_Df250TriggerTime(...);
319  //
320  // where the "..." represents whatever arguments are passed into the
321  // Df250TriggerTime constructor.
322  //
323  #define makeallocator(A) template<typename... Args> \
324  A* NEW_##A(Args&&... args){ \
325  A* t = NULL; \
326  if(v##A##_pool.empty()){ \
327  t = new A(std::forward<Args>(args)...); \
328  }else{ \
329  t = v##A##_pool.back(); \
330  v##A##_pool.pop_back(); \
331  t->ClearAssociatedObjects(); \
332  new(t) A(std::forward<Args>(args)...); \
333  } \
334  v##A.push_back(t); \
335  return t; \
336  }
339 
340  // Constructor and destructor
341  DParsedEvent(uint64_t MAX_OBJECT_RECYCLES=1000):in_use(false),Nrecycled(0),MAX_RECYCLES(MAX_OBJECT_RECYCLES),borptrs(NULL){}
342  #define printcounts(A) if(!v##A.empty()) cout << v##A.size() << " : " << #A << endl;
343  #define printpoolcounts(A) if(!v##A##_pool.empty()) cout << v##A##_pool.size() << " : " << #A << "_pool" << endl;
344  virtual ~DParsedEvent(){
345 // cout << "----- DParsedEvent (" << this << ") -------" << endl;
346 // MyTypes(printcounts);
347 // MyBORTypes(printcounts);
348 // MyTypes(printpoolcounts);
349  Delete();
350  }
351 
352  protected:
353  map<JEventLoop*, DFactoryPointers> factory_pointers;
354 
355 
356 };
357 
358 // clean out #defines to avoid compilation warnings with other classes (e.g. DTranslationTable)
359 #undef MyTypes
360 #undef MyDerivedTypes
361 #undef makevector
362 #undef makepoolvector
363 #undef returntopool
364 #undef clearvectors
365 #undef deletevector
366 #undef deletepool
367 #undef clearpoolvectors
368 #undef makefactoryptr
369 #undef copyfactoryptr
370 #undef copytofactory
371 #undef copybortofactory
372 #undef setevntcalled
373 #undef keepownership
374 #undef copytofactorynonempty
375 #undef setevntcallednonempty
376 #undef keepownershipnonempty
377 #undef checkclassname
378 #undef checknonemptyderivedclassname
379 #undef addclassname
380 #undef makeallocator
381 #undef printcounts
382 #undef printpoolcounts
383 
384 
385 #endif // _DParsedEvent_
386 
#define makeallocator(A)
Definition: DParsedEvent.h:323
#define deletevector(A)
Definition: DParsedEvent.h:188
DParsedEvent(uint64_t MAX_OBJECT_RECYCLES=1000)
Definition: DParsedEvent.h:341
#define MyBORTypes(X)
Definition: DBORptrs.h:22
uint64_t istreamorder
Definition: DParsedEvent.h:141
bool IsParsedDataType(string &classname) const
Definition: DParsedEvent.h:270
uint64_t MAX_RECYCLES
Definition: DParsedEvent.h:137
#define setevntcallednonempty(A)
Definition: DParsedEvent.h:245
uint64_t Nrecycled
Definition: DParsedEvent.h:136
#define clearvectors(A)
Definition: DParsedEvent.h:173
#define copytofactory(A)
Definition: DParsedEvent.h:240
void GetParsedDataTypes(vector< string > &classnames, bool include_all=false) const
Definition: DParsedEvent.h:289
char string[256]
uint64_t event_status_bits
Definition: DParsedEvent.h:144
#define clearpoolvectors(A)
Definition: DParsedEvent.h:175
#define setevntcalled(A)
Definition: DParsedEvent.h:242
#define copytofactorynonempty(A)
Definition: DParsedEvent.h:244
bool copied_to_factories
Definition: DParsedEvent.h:138
#define keepownership(A)
Definition: DParsedEvent.h:243
#define deletepool(A)
Definition: DParsedEvent.h:174
virtual ~DParsedEvent()
Definition: DParsedEvent.h:344
#define MyNoPoolTypes(X)
Definition: DParsedEvent.h:128
#define makepoolvector(A)
Definition: DParsedEvent.h:164
#define makefactoryptr(A)
Definition: DParsedEvent.h:214
void Delete(void)
Definition: DParsedEvent.h:189
#define checkclassname(A)
Definition: DParsedEvent.h:269
#define copyfactoryptr(A)
Definition: DParsedEvent.h:215
bool IsNonEmptyDerivedDataType(string &classname) const
Definition: DParsedEvent.h:281
void Clear(void)
Definition: DParsedEvent.h:176
#define addclassname(A)
Definition: DParsedEvent.h:288
DBORptrs * borptrs
Definition: DParsedEvent.h:147
uint64_t event_number
Definition: DParsedEvent.h:143
#define MyDerivedTypes(X)
Definition: DParsedEvent.h:116
#define copybortofactory(A)
Definition: DParsedEvent.h:241
atomic< bool > in_use
Definition: DParsedEvent.h:135
uint64_t run_number
Definition: DParsedEvent.h:142
#define keepownershipnonempty(A)
Definition: DParsedEvent.h:246
#define MyTypes(X)
Definition: DParsedEvent.h:77
uint32_t buff_len
Definition: DParsedEvent.h:140
void Init(JEventLoop *loop)
Definition: DParsedEvent.h:226
map< JEventLoop *, DFactoryPointers > factory_pointers
Definition: DParsedEvent.h:353
void CopyToFactories(JEventLoop *loop)
Definition: DParsedEvent.h:247
void Prune(void)
Definition: DParsedEvent.h:204
#define checknonemptyderivedclassname(A)
Definition: DParsedEvent.h:280
#define returntopool(A)
Definition: DParsedEvent.h:172
#define makevector(A)
Definition: DParsedEvent.h:155