Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion io/io/inc/ROOT/TBufferMerger.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private:
std::mutex fWriteMutex; //< Mutex used for the condition variable
std::condition_variable fCV; //< Condition variable used to wait for data
std::queue<TBufferFile *> fQueue; //< Queue to which data is pushed and merged
std::unique_ptr<TFile> fFile; //< Output file, owned by the user
std::unique_ptr<TFile> fFile; //< Output file, owned by this class
std::unique_ptr<std::thread> fMergingThread; //< Worker thread that writes to disk
std::vector<std::weak_ptr<TBufferMergerFile>> fAttachedFiles; //< Attached files

Expand Down
1 change: 1 addition & 0 deletions io/io/src/TBufferMerger.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ TBufferMerger::~TBufferMerger()
fCV.notify_one();

fMergingThread->join();
fFile->Close();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should'nt it be SafeDelete(fFile);
i.e. is the object pointed to by fFile re-used after this statement?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, fFile is owned by the TBufferMerger class, it's a unique_ptr. It gets destroyed with the server. I just noticed, however, that the documentation on the header is wrong, I will update it.

}

std::shared_ptr<TBufferMergerFile> TBufferMerger::GetFile()
Expand Down
30 changes: 19 additions & 11 deletions tree/treeplayer/inc/ROOT/TDataFrameInterface.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define ROOT_TDATAFRAME_INTERFACE

#include "ROOT/TActionResultProxy.hxx"
#include "ROOT/TBufferMerger.hxx"
#include "ROOT/TDFNodes.hxx"
#include "ROOT/TDFOperations.hxx"
#include "ROOT/TDFUtils.hxx"
Expand Down Expand Up @@ -1066,26 +1067,33 @@ protected:
}

{
std::unique_ptr<TFile> ofile(TFile::Open(filename.c_str(), "RECREATE"));
TTree t(treename.c_str(), treename.c_str());
auto df = GetDataFrameChecked();
unsigned int nSlots = df->GetNSlots();
TBufferMerger merger(filename.c_str(), "RECREATE");
std::vector<std::shared_ptr<TBufferMergerFile>> files(nSlots);
std::vector<std::unique_ptr<TTree>> trees(nSlots);

static bool firstEvt = true;
auto fillTree = [&merger, &trees, &files, &bnames, &treename](unsigned int slot, Args &... args) {
if (!trees[slot]) {
files[slot] = merger.GetFile();
trees[slot].reset(new TTree(treename.c_str(), treename.c_str()));

auto fillTree = [&t, &bnames](Args &... args) {
if (firstEvt) {
// hack to call TTree::Branch on all variadic template arguments
std::initializer_list<int> expander = {(t.Branch(bnames[S].c_str(), &args), 0)..., 0};
std::initializer_list<int> expander = {(trees[slot]->Branch(bnames[S].c_str(), &args), 0)..., 0};

(void)expander; // avoid unused variable warnings for older compilers such as gcc 4.9
firstEvt = false;
}
t.Fill();

trees[slot]->Fill();
};

Foreach(fillTree, {bnames[S]...});
ForeachSlot(fillTree, {bnames[S]...});

for (auto &&tree : trees) tree->Write();
for (auto &&file : files) file->Write();

t.Write();
firstEvt = true;
trees.clear();
files.clear();
}
// Now we mimic a constructor for the TDataFrame. We cannot invoke it here
// since this would introduce a cyclic headers dependency.
Expand Down