CbmRoot
Loading...
Searching...
No Matches
CbmReadoutBuffer.h
Go to the documentation of this file.
1/* Copyright (C) 2015-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer], Florian Uhlig */
4
5/*
6 * CbmReadoutBuffer.h
7 *
8 * Created on: 26.05.2015
9 * Author: vfriese
10 */
11
12#ifndef CBMREADOUTBUFFER_H
13#define CBMREADOUTBUFFER_H 1
14
15#include <FairRootManager.h>
16#include <FairWriteoutBuffer.h>
17#include <Logger.h>
18
19#include <TClonesArray.h>
20#include <TObject.h>
21
22#include <cassert>
23#include <map>
24#include <vector>
25
26// The data class must implement the methods Double_t GetTimeStart(),
27// Double_t GetTimeStop(), and void SetTimeStop(Double_t),
28// as well as a copy constructor (default one is fine).
29// Data must inherit from TObject.
30
31
32template<class Data>
33class CbmReadoutBuffer : public FairWriteoutBuffer {
34
35public:
36 // ---------------------------------------------------------------------
42 CbmReadoutBuffer() : FairWriteoutBuffer(), fBuffer(), fBufferIt(), fOldIt(), fArray(nullptr), fWriteToArray(kFALSE) {}
43 // ---------------------------------------------------------------------
44
45 // ---------------------------------------------------------------------
56 CbmReadoutBuffer(TString branchName, TString folderName, Bool_t persistence = kTRUE)
57 : FairWriteoutBuffer()
58 , fBuffer()
59 , fBufferIt()
60 , fOldIt()
61 , fArray(nullptr)
62 , fWriteToArray(kTRUE)
63 {
64
65 if (FairRootManager::Instance()) {
66 Data* data = new Data();
67 const char* className = data->ClassName();
68 delete data;
69 LOG(info) << "Class name is " << className;
70 fArray = FairRootManager::Instance()->Register(branchName, className, folderName, persistence);
71 }
72 }
73 // ---------------------------------------------------------------------
76
77
78 // ---------------------------------------------------------------------
85 {
86 if (fBuffer.size()) LOG(warn) << "Destroying non-empty readout buffer! Number of data: " << fBuffer.size();
87 for (fBufferIt = fBuffer.begin(); fBufferIt != fBuffer.end(); fBufferIt++)
88 if (fBufferIt->second) delete fBufferIt->second;
89 }
90 // ---------------------------------------------------------------------
91
92
93 // ---------------------------------------------------------------------
98 virtual void AddNewDataToTClonesArray(FairTimeStamp* /*data*/) {}
99 // ---------------------------------------------------------------------
100
101
102 // ---------------------------------------------------------------------
108 Bool_t CheckData(Data* data) { return (data->GetTimeStop() >= data->GetTimeStart()); }
109 // ---------------------------------------------------------------------
110
111
112 // ---------------------------------------------------------------------
120 Bool_t CheckInterference(Data* data1, Data* data2)
121 {
122 if (data1->GetTimeStop() < data2->GetTimeStart()) return kFALSE;
123 if (data2->GetTimeStop() < data1->GetTimeStart()) return kFALSE;
124 return kTRUE;
125 }
126 // ---------------------------------------------------------------------
127
128
129 // ---------------------------------------------------------------------
133 virtual void DeleteOldData()
134 {
135 if (fArray) fArray->Delete();
136 }
137 // ---------------------------------------------------------------------
138
139
140 // ---------------------------------------------------------------------
145 virtual void EraseDataFromDataMap(FairTimeStamp*) {}
146 // ---------------------------------------------------------------------
147
148
149 // ---------------------------------------------------------------------
160 void Fill(UInt_t address, Data* data)
161 {
162
163 LOG(debug4) << "RO: Filling data at t = " << data->GetTimeStart() << " in address " << address;
164
165 // --- Check data for consistency (start/stop time)
166 if (!CheckData(data)) {
167 LOG(fatal) << GetName() << ": inconsistent data input to Fill(). "
168 << "Start time is " << data->GetTimeStart() << " stop time is " << data->GetTimeStop();
169 }
170
171 // --- Loop over all present data with same address
172 // --- Pick the first to which the interference criterion applies.
173 Bool_t dataFound = kFALSE;
174 for (fBufferIt = fBuffer.lower_bound(address); fBufferIt != fBuffer.upper_bound(address); fBufferIt++) {
175
176 // --- Check interference of buffer data with old data. If so, jump
177 // --- out of loop
178 if (CheckInterference(data, fBufferIt->second)) {
179 dataFound = kTRUE;
180 break;
181 } //? Interference
182
183 } //# Data at same address
184
185 // --- Action of interfering data found in the buffer
186 if (dataFound) {
187
188 // --- Call Modify method
189 std::vector<Data*> newDataList;
190 Merge(fBufferIt->second, data, newDataList);
191
192 // --- Check return data list for non-interference
193 // --- Modify has to be implemented in such as way as to return a
194 // --- list (vector) of non-interfering data objects. This is
195 // --- checked here to prevent unwanted behaviour
196 // --- (e.g., endless loops).
197 Int_t nData = newDataList.size();
198 for (Int_t iData1 = 0; iData1 < nData; iData1++) {
199 for (Int_t iData2 = iData1 + 1; iData2 < nData; iData2++) {
200 if (CheckInterference(newDataList[iData1], newDataList[iData2]))
201 LOG(fatal) << GetName() << ": Interfering data in return from Modify! "
202 << "Data 1: t(start) = " << newDataList[iData1]->GetTimeStart()
203 << " ns, t(stop) = " << newDataList[iData1]->GetTimeStop()
204 << ", Data 2: t(start) = " << newDataList[iData2]->GetTimeStart()
205 << " ns, t(stop) = " << newDataList[iData2]->GetTimeStop();
206 } //# data in vector (second loop)
207 } //# data in vector (first loop)
208
209 // --- Remove old data from buffer and delete added data object
210 if (fBufferIt->second) delete fBufferIt->second;
211 fBuffer.erase(fBufferIt);
212 delete data;
213
214 // --- Fill new data to buffer, still checking for existing ones
215 for (UInt_t iData = 0; iData < newDataList.size(); iData++) {
216 LOG(debug4) << "RO: Filling modified data at address " << address
217 << ", t = " << newDataList[iData]->GetTimeStart() << " to " << newDataList[iData]->GetTimeStop();
218 Fill(address, newDataList[iData]);
219 } //# result data of Modify
220
221 } //? Interfering data
222
223 // --- No interference; just insert data into buffer
224 else {
225
226 fBuffer.insert(std::pair<UInt_t, Data*>(address, data));
227 LOG(debug4) << "RO: Insert data at address " << address << ", t = " << data->GetTimeStart() << " to "
228 << data->GetTimeStop();
229
230 } //? No interference
231 }
232 // ---------------------------------------------------------------------
233
234
235 // ---------------------------------------------------------------------
240 virtual void FillDataMap(FairTimeStamp*, double /*activeTime*/) {}
241 // ---------------------------------------------------------------------
242
243
244 // ---------------------------------------------------------------------
249 virtual double FindTimeForData(FairTimeStamp*) { return -1.; }
250 // ---------------------------------------------------------------------
251
252
253 // ---------------------------------------------------------------------
257 virtual Int_t GetNData() { return fBuffer.size(); }
258 // ---------------------------------------------------------------------
259
260
261 // ---------------------------------------------------------------------
262 virtual Int_t Merge(Data* oldData1, Data* oldData2, std::vector<Data*>& newDataList)
263 {
264
265 // Default prescription: return earlier data, skip the later one,
266 // but set the stop time of the result to the maximum of the
267 // two stop times
268 Data* firstData = (oldData1->GetTimeStart() < oldData2->GetTimeStart() ? oldData1 : oldData2);
269 Double_t stopTime = std::max(oldData1->GetTimeStop(), oldData2->GetTimeStop());
270
271 // Create new data object
272 Data* newData = new Data(*firstData);
273 newData->SetTimeStop(stopTime);
274
275 // Add new data object to the result list
276 newDataList.push_back(newData);
277
278 return 1; // Number of return data objects
279 }
280 // ---------------------------------------------------------------------
281
282
283 // ---------------------------------------------------------------------
290 virtual void WriteOutAllData() { WriteOutData(-1.); }
291 // ---------------------------------------------------------------------
292
293
294 // ---------------------------------------------------------------------
306 Int_t ReadOutData(Double_t time, std::vector<Data*>& dataList)
307 {
308
309 LOG(debug) << "RO Buffer: read out at t = " << time << ", buffer size " << fBuffer.size();
310 if (!dataList.empty()) dataList.clear();
311
312 Int_t nData = 0;
313 fBufferIt = fBuffer.begin();
314 while (fBufferIt != fBuffer.end()) {
315
316 UInt_t address = fBufferIt->first;
317 Data* data = fBufferIt->second;
318
319 LOG(debug4) << "Buffer entry: " << address << " " << data->GetTimeStart();
320
321 // --- Assert valid data object
322 assert(data);
323
324 // --- Skip if stop time after readout time
325 if (time >= 0. && data->GetTimeStop() > time) {
326 fBufferIt++;
327 continue;
328 }
329
330 // --- Fill output vector with data pointers
331 LOG(debug4) << "RO: read out data at t = " << data->GetTimeStart();
332 dataList.push_back(data);
333
334 // --- Remove element from buffer
336 fBufferIt++;
337 fBuffer.erase(fOldIt);
338
339 nData++;
340 } //# elements in buffer
341
342 return nData;
343 }
344 // ---------------------------------------------------------------------
345
346
347 // ---------------------------------------------------------------------
357 virtual void WriteOutData(Double_t time)
358 {
359
360 if (!fWriteToArray) return;
361
362 LOG(info) << "RO Buffer: write out at t = " << time << ", buffer size " << fBuffer.size() << ", array size "
363 << fArray->GetEntriesFast();
364
365 Int_t nDataWritten = 0;
366 fBufferIt = fBuffer.begin();
367 while (fBufferIt != fBuffer.end()) {
368
369 UInt_t address = fBufferIt->first;
370 Data* data = fBufferIt->second;
371
372 LOG(debug4) << "Buffer entry: " << address << " " << data->GetTimeStart();
373
374 // --- Assert valid data object
375 assert(data);
376
377 // --- Skip if stop time after readout time
378 if (time >= 0. && data->GetTimeStop() > time) {
379 fBufferIt++;
380 continue;
381 }
382
383 // --- Copy data to TClonesArray
384 if (fArray) {
385 LOG(debug4) << "RO: Writing to array: t = " << data->GetTimeStart();
386 new ((*fArray)[fArray->GetEntriesFast()]) Data(*data);
387 }
388
389 // --- Delete data and remove element from buffer
390 delete data;
392 fBufferIt++;
393 fBuffer.erase(fOldIt);
394
395 nDataWritten++;
396
397 } //# buffer elements
398
399 LOG(info) << "RO Buffer: wrote " << nDataWritten << " data, buffer size " << fBuffer.size() << ", array size "
400 << fArray->GetEntriesFast();
401 }
402 // ---------------------------------------------------------------------
403
404
405protected:
406 std::multimap<UInt_t, Data*> fBuffer;
407 typename std::multimap<UInt_t, Data*>::iterator fBufferIt;
408 typename std::multimap<UInt_t, Data*>::iterator fOldIt;
409 TClonesArray* fArray;
411};
412
413#endif /* CBMREADOUTBUFFER_H_ */
virtual Int_t Merge(Data *oldData1, Data *oldData2, std::vector< Data * > &newDataList)
virtual void FillDataMap(FairTimeStamp *, double)
std::multimap< UInt_t, Data * > fBuffer
std::multimap< UInt_t, Data * >::iterator fBufferIt
Int_t ReadOutData(Double_t time, std::vector< Data * > &dataList)
void Fill(UInt_t address, Data *data)
virtual void AddNewDataToTClonesArray(FairTimeStamp *)
CbmReadoutBuffer(TString branchName, TString folderName, Bool_t persistence=kTRUE)
virtual void EraseDataFromDataMap(FairTimeStamp *)
virtual double FindTimeForData(FairTimeStamp *)
std::multimap< UInt_t, Data * >::iterator fOldIt
CbmReadoutBuffer & operator=(const CbmReadoutBuffer &)=delete
Bool_t CheckInterference(Data *data1, Data *data2)
Bool_t CheckData(Data *data)
virtual void WriteOutData(Double_t time)
virtual void WriteOutAllData()
virtual Int_t GetNData()
CbmReadoutBuffer(const CbmReadoutBuffer &)=delete
TClonesArray * fArray
virtual void DeleteOldData()
virtual ~CbmReadoutBuffer()