Hi experts,
I am trying to use the parrallel TTree-Reader/Processor.
This is the code I am using:
class MergeVec
{
private:
std::vector<o2::trd::TrackQC> tracks{};
std::mutex mutex{};
unsigned int id{0};
static MergeVec* instance;
MergeVec() {}
public:
void Merge(const std::vector<o2::trd::TrackQC> vec)
{
const std::lock_guard<std::mutex> lock(mutex);
auto before = tracks.size();
tracks.reserve(tracks.size() + std::distance(vec.begin(), vec.end()));
tracks.insert(tracks.end(), vec.begin(), vec.end());
auto after = tracks.size();
std::cout << "ID " << id << " from " << before << " to " << after << std::endl;
++id;
}
static MergeVec* getInstance()
{
if (!instance)
instance = new MergeVec;
return instance;
}
std::vector<o2::trd::TrackQC> getData()
{
return this->tracks;
}
};
MergeVec* MergeVec::instance = 0;
void dEdxTPCMP()
{
gROOT->SetBatch();
ROOT::EnableImplicitMT();
TChain chain("qc");
chain.Add("trdQC*.root");
const auto nFiles = chain.GetListOfFiles()->GetEntries();
auto gVec = MergeVec::getInstance();
auto workItem = [&gVec](TTreeReader& reader) {
auto hist = new TH2D("hist", "dEdx", 500, 0, 5, 500, 0, 500);
TTreeReaderValue<std::vector<o2::trd::TrackQC>> qc(reader, "trackQC");
std::vector<o2::trd::TrackQC> goodTracks;
while (reader.Next()) {
for (const auto& q : *qc.Get()) {
goodTracks.push_back(q);
}
}
gVec->Merge(goodTracks);
return hist;
};
ROOT::TTreeProcessorMP workers(nFiles);
auto hist = workers.Process(chain, workItem, "qc");
std::cout << "Got " << gVec->getData().size() << std::endl;
}
The workItem I implement captures a reference to a var (which is a probably over-engineered class as singleton) used for merging a vector produced in the lambda to a global vector.
However running this macro gives me:
...
ID 0 from 0 to 3247923
ID 0 from 0 to 1283188
Got 0
Basically I never copy the data out of the lambda.
Maybe I oversaw an implementation detail but I do not understand why this would not work even if side effects are discouraged.
Any help is appreciated.