CbmRoot
CbmReadoutBuffer.h
Go to the documentation of this file.
1 /*
2  * CbmReadoutBuffer.h
3  *
4  * Created on: 26.05.2015
5  * Author: vfriese
6  */
7 
8 #ifndef CBMREADOUTBUFFER_H
9 #define CBMREADOUTBUFFER_H 1
10 
11 #include <FairLogger.h>
12 #include <FairRootManager.h>
13 #include <FairWriteoutBuffer.h>
14 #include <TClonesArray.h>
15 #include <TObject.h>
16 #include <cassert>
17 #include <map>
18 #include <vector>
19 
20 // The data class must implement the methods Double_t GetTimeStart(),
21 // Double_t GetTimeStop(), and void SetTimeStop(Double_t),
22 // as well as a copy constructor (default one is fine).
23 // Data must inherit from TObject.
24 
25 
26 template<class Data>
27 class CbmReadoutBuffer : public FairWriteoutBuffer {
28 
29 public:
30  // ---------------------------------------------------------------------
37  : FairWriteoutBuffer()
38  , fBuffer()
39  , fBufferIt()
40  , fOldIt()
41  , fArray(nullptr)
42  , fWriteToArray(kFALSE) {}
43  // ---------------------------------------------------------------------
44 
45  // ---------------------------------------------------------------------
56  CbmReadoutBuffer(TString branchName,
57  TString folderName,
58  Bool_t persistence = kTRUE)
59  : FairWriteoutBuffer()
60  , fBuffer()
61  , fBufferIt()
62  , fOldIt()
63  , fArray(nullptr)
64  , fWriteToArray(kTRUE) {
65 
66  if (FairRootManager::Instance()) {
67  Data* data = new Data();
68  const char* className = data->ClassName();
69  delete data;
70  LOG(info) << "Class name is " << className;
71  fArray = FairRootManager::Instance()->Register(
72  branchName, className, folderName, persistence);
73  }
74  }
75  // ---------------------------------------------------------------------
78 
79 
80  // ---------------------------------------------------------------------
86  virtual ~CbmReadoutBuffer() {
87  if (fBuffer.size())
88  LOG(warn) << "Destroying non-empty readout buffer! Number of data: "
89  << fBuffer.size();
90  for (fBufferIt = fBuffer.begin(); fBufferIt != fBuffer.end(); fBufferIt++)
91  if (fBufferIt->second) delete fBufferIt->second;
92  }
93  // ---------------------------------------------------------------------
94 
95 
96  // ---------------------------------------------------------------------
101  virtual void AddNewDataToTClonesArray(FairTimeStamp* /*data*/) {}
102  // ---------------------------------------------------------------------
103 
104 
105  // ---------------------------------------------------------------------
111  Bool_t CheckData(Data* data) {
112  return (data->GetTimeStop() >= data->GetTimeStart());
113  }
114  // ---------------------------------------------------------------------
115 
116 
117  // ---------------------------------------------------------------------
125  Bool_t CheckInterference(Data* data1, Data* data2) {
126  if (data1->GetTimeStop() < data2->GetTimeStart()) return kFALSE;
127  if (data2->GetTimeStop() < data1->GetTimeStart()) return kFALSE;
128  return kTRUE;
129  }
130  // ---------------------------------------------------------------------
131 
132 
133  // ---------------------------------------------------------------------
137  virtual void DeleteOldData() {
138  if (fArray) fArray->Delete();
139  }
140  // ---------------------------------------------------------------------
141 
142 
143  // ---------------------------------------------------------------------
148  virtual void EraseDataFromDataMap(FairTimeStamp*) {}
149  // ---------------------------------------------------------------------
150 
151 
152  // ---------------------------------------------------------------------
163  void Fill(UInt_t address, Data* data) {
164 
165  LOG(debug4) << "RO: Filling data at t = " << data->GetTimeStart()
166  << " in address " << address;
167 
168  // --- Check data for consistency (start/stop time)
169  if (!CheckData(data)) {
170  LOG(fatal) << GetName() << ": inconsistent data input to Fill(). "
171  << "Start time is " << data->GetTimeStart() << " stop time is "
172  << data->GetTimeStop();
173  }
174 
175  // --- Loop over all present data with same address
176  // --- Pick the first to which the interference criterion applies.
177  Bool_t dataFound = kFALSE;
178  for (fBufferIt = fBuffer.lower_bound(address);
179  fBufferIt != fBuffer.upper_bound(address);
180  fBufferIt++) {
181 
182  // --- Check interference of buffer data with old data. If so, jump
183  // --- out of loop
184  if (CheckInterference(data, fBufferIt->second)) {
185  dataFound = kTRUE;
186  break;
187  } //? Interference
188 
189  } //# Data at same address
190 
191  // --- Action of interfering data found in the buffer
192  if (dataFound) {
193 
194  // --- Call Modify method
195  std::vector<Data*> newDataList;
196  Merge(fBufferIt->second, data, newDataList);
197 
198  // --- Check return data list for non-interference
199  // --- Modify has to be implemented in such as way as to return a
200  // --- list (vector) of non-interfering data objects. This is
201  // --- checked here to prevent unwanted behaviour
202  // --- (e.g., endless loops).
203  Int_t nData = newDataList.size();
204  for (Int_t iData1 = 0; iData1 < nData; iData1++) {
205  for (Int_t iData2 = iData1 + 1; iData2 < nData; iData2++) {
206  if (CheckInterference(newDataList[iData1], newDataList[iData2]))
207  LOG(fatal)
208  << GetName() << ": Interfering data in return from Modify! "
209  << "Data 1: t(start) = " << newDataList[iData1]->GetTimeStart()
210  << " ns, t(stop) = " << newDataList[iData1]->GetTimeStop()
211  << ", Data 2: t(start) = " << newDataList[iData2]->GetTimeStart()
212  << " ns, t(stop) = " << newDataList[iData2]->GetTimeStop();
213  } //# data in vector (second loop)
214  } //# data in vector (first loop)
215 
216  // --- Remove old data from buffer and delete added data object
217  if (fBufferIt->second) delete fBufferIt->second;
218  fBuffer.erase(fBufferIt);
219  delete data;
220 
221  // --- Fill new data to buffer, still checking for existing ones
222  for (UInt_t iData = 0; iData < newDataList.size(); iData++) {
223  LOG(debug4) << "RO: Filling modified data at address " << address
224  << ", t = " << newDataList[iData]->GetTimeStart() << " to "
225  << newDataList[iData]->GetTimeStop();
226  Fill(address, newDataList[iData]);
227  } //# result data of Modify
228 
229  } //? Interfering data
230 
231  // --- No interference; just insert data into buffer
232  else {
233 
234  fBuffer.insert(std::pair<UInt_t, Data*>(address, data));
235  LOG(debug4) << "RO: Insert data at address " << address
236  << ", t = " << data->GetTimeStart() << " to "
237  << data->GetTimeStop();
238 
239  } //? No interference
240  }
241  // ---------------------------------------------------------------------
242 
243 
244  // ---------------------------------------------------------------------
249  virtual void FillDataMap(FairTimeStamp*, double /*activeTime*/) {}
250  // ---------------------------------------------------------------------
251 
252 
253  // ---------------------------------------------------------------------
258  virtual double FindTimeForData(FairTimeStamp*) { return -1.; }
259  // ---------------------------------------------------------------------
260 
261 
262  // ---------------------------------------------------------------------
266  virtual Int_t GetNData() { return fBuffer.size(); }
267  // ---------------------------------------------------------------------
268 
269 
270  // ---------------------------------------------------------------------
271  virtual Int_t
272  Merge(Data* oldData1, Data* oldData2, std::vector<Data*>& newDataList) {
273 
274  // Default prescription: return earlier data, skip the later one,
275  // but set the stop time of the result to the maximum of the
276  // two stop times
277  Data* firstData =
278  (oldData1->GetTimeStart() < oldData2->GetTimeStart() ? oldData1
279  : oldData2);
280  Double_t stopTime =
281  std::max(oldData1->GetTimeStop(), oldData2->GetTimeStop());
282 
283  // Create new data object
284  Data* newData = new Data(*firstData);
285  newData->SetTimeStop(stopTime);
286 
287  // Add new data object to the result list
288  newDataList.push_back(newData);
289 
290  return 1; // Number of return data objects
291  }
292  // ---------------------------------------------------------------------
293 
294 
295  // ---------------------------------------------------------------------
302  virtual void WriteOutAllData() { WriteOutData(-1.); }
303  // ---------------------------------------------------------------------
304 
305 
306  // ---------------------------------------------------------------------
318  Int_t ReadOutData(Double_t time, std::vector<Data*>& dataList) {
319 
320  LOG(debug) << "RO Buffer: read out at t = " << time << ", buffer size "
321  << fBuffer.size();
322  if (!dataList.empty()) dataList.clear();
323 
324  Int_t nData = 0;
325  fBufferIt = fBuffer.begin();
326  while (fBufferIt != fBuffer.end()) {
327 
328  UInt_t address = fBufferIt->first;
329  Data* data = fBufferIt->second;
330 
331  LOG(debug4) << "Buffer entry: " << address << " " << data->GetTimeStart();
332 
333  // --- Assert valid data object
334  assert(data);
335 
336  // --- Skip if stop time after readout time
337  if (time >= 0. && data->GetTimeStop() > time) {
338  fBufferIt++;
339  continue;
340  }
341 
342  // --- Fill output vector with data pointers
343  LOG(debug4) << "RO: read out data at t = " << data->GetTimeStart();
344  dataList.push_back(data);
345 
346  // --- Remove element from buffer
347  fOldIt = fBufferIt;
348  fBufferIt++;
349  fBuffer.erase(fOldIt);
350 
351  nData++;
352  } //# elements in buffer
353 
354  return nData;
355  }
356  // ---------------------------------------------------------------------
357 
358 
359  // ---------------------------------------------------------------------
369  virtual void WriteOutData(Double_t time) {
370 
371  if (!fWriteToArray) return;
372 
373  LOG(info) << "RO Buffer: write out at t = " << time << ", buffer size "
374  << fBuffer.size() << ", array size " << fArray->GetEntriesFast();
375 
376  Int_t nDataWritten = 0;
377  fBufferIt = fBuffer.begin();
378  while (fBufferIt != fBuffer.end()) {
379 
380  UInt_t address = fBufferIt->first;
381  Data* data = fBufferIt->second;
382 
383  LOG(debug4) << "Buffer entry: " << address << " " << data->GetTimeStart();
384 
385  // --- Assert valid data object
386  assert(data);
387 
388  // --- Skip if stop time after readout time
389  if (time >= 0. && data->GetTimeStop() > time) {
390  fBufferIt++;
391  continue;
392  }
393 
394  // --- Copy data to TClonesArray
395  if (fArray) {
396  LOG(debug4) << "RO: Writing to array: t = " << data->GetTimeStart();
397  new ((*fArray)[fArray->GetEntriesFast()]) Data(*data);
398  }
399 
400  // --- Delete data and remove element from buffer
401  delete data;
402  fOldIt = fBufferIt;
403  fBufferIt++;
404  fBuffer.erase(fOldIt);
405 
406  nDataWritten++;
407 
408  } //# buffer elements
409 
410  LOG(info) << "RO Buffer: wrote " << nDataWritten << " data, buffer size "
411  << fBuffer.size() << ", array size " << fArray->GetEntriesFast();
412  }
413  // ---------------------------------------------------------------------
414 
415 
416 protected:
417  std::multimap<UInt_t, Data*> fBuffer;
418  typename std::multimap<UInt_t, Data*>::iterator fBufferIt;
419  typename std::multimap<UInt_t, Data*>::iterator fOldIt;
420  TClonesArray* fArray;
422 };
423 
424 #endif /* CBMREADOUTBUFFER_H_ */
CbmReadoutBuffer::WriteOutData
virtual void WriteOutData(Double_t time)
Definition: CbmReadoutBuffer.h:369
CbmReadoutBuffer::fBufferIt
std::multimap< UInt_t, Data * >::iterator fBufferIt
Definition: CbmReadoutBuffer.h:418
CbmReadoutBuffer::operator=
CbmReadoutBuffer & operator=(const CbmReadoutBuffer &)=delete
CbmReadoutBuffer::DeleteOldData
virtual void DeleteOldData()
Definition: CbmReadoutBuffer.h:137
CbmReadoutBuffer::Fill
void Fill(UInt_t address, Data *data)
Definition: CbmReadoutBuffer.h:163
CbmReadoutBuffer::CheckData
Bool_t CheckData(Data *data)
Definition: CbmReadoutBuffer.h:111
CbmReadoutBuffer::WriteOutAllData
virtual void WriteOutAllData()
Definition: CbmReadoutBuffer.h:302
CbmReadoutBuffer::CheckInterference
Bool_t CheckInterference(Data *data1, Data *data2)
Definition: CbmReadoutBuffer.h:125
CbmReadoutBuffer::fOldIt
std::multimap< UInt_t, Data * >::iterator fOldIt
Definition: CbmReadoutBuffer.h:419
CbmReadoutBuffer::CbmReadoutBuffer
CbmReadoutBuffer(TString branchName, TString folderName, Bool_t persistence=kTRUE)
Definition: CbmReadoutBuffer.h:56
CbmReadoutBuffer::FindTimeForData
virtual double FindTimeForData(FairTimeStamp *)
Definition: CbmReadoutBuffer.h:258
CbmReadoutBuffer::AddNewDataToTClonesArray
virtual void AddNewDataToTClonesArray(FairTimeStamp *)
Definition: CbmReadoutBuffer.h:101
CbmReadoutBuffer::fArray
TClonesArray * fArray
Definition: CbmReadoutBuffer.h:420
CbmReadoutBuffer::FillDataMap
virtual void FillDataMap(FairTimeStamp *, double)
Definition: CbmReadoutBuffer.h:249
CbmReadoutBuffer::fWriteToArray
Bool_t fWriteToArray
Definition: CbmReadoutBuffer.h:421
CbmReadoutBuffer::ReadOutData
Int_t ReadOutData(Double_t time, std::vector< Data * > &dataList)
Definition: CbmReadoutBuffer.h:318
CbmReadoutBuffer::EraseDataFromDataMap
virtual void EraseDataFromDataMap(FairTimeStamp *)
Definition: CbmReadoutBuffer.h:148
CbmReadoutBuffer
Definition: CbmReadoutBuffer.h:27
CbmReadoutBuffer::CbmReadoutBuffer
CbmReadoutBuffer(const CbmReadoutBuffer &)=delete
CbmReadoutBuffer::fBuffer
std::multimap< UInt_t, Data * > fBuffer
Definition: CbmReadoutBuffer.h:417
max
friend F32vec4 max(const F32vec4 &a, const F32vec4 &b)
Definition: L1/vectors/P4_F32vec4.h:36
CbmReadoutBuffer::CbmReadoutBuffer
CbmReadoutBuffer()
Definition: CbmReadoutBuffer.h:36
CbmReadoutBuffer::~CbmReadoutBuffer
virtual ~CbmReadoutBuffer()
Definition: CbmReadoutBuffer.h:86
CbmReadoutBuffer::Merge
virtual Int_t Merge(Data *oldData1, Data *oldData2, std::vector< Data * > &newDataList)
Definition: CbmReadoutBuffer.h:272
CbmReadoutBuffer::GetNData
virtual Int_t GetNData()
Definition: CbmReadoutBuffer.h:266