-
Notifications
You must be signed in to change notification settings - Fork 1.4k
[cont] Clear "C" TClonesArray: Remove object from TProcessID-table ; Allow removing without destructing #18439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 12 commits
ced4058
9ac9723
b778609
118d9e2
f8fd22b
c8b5dd2
195634d
6373748
63c7edf
2d728f7
e6ba89c
f712fe9
b952a63
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| #include "TestRefObj.h" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| #ifndef TESTREFOBJ_H | ||
| #define TESTREFOBJ_H | ||
|
|
||
| #include "TRef.h" | ||
| #include "TRefArray.h" | ||
|
|
||
| // https://its.cern.ch/jira/browse/ROOT-7249 | ||
| class TestRefObj : public TObject { | ||
| protected: | ||
| TRefArray lChildren; | ||
|
|
||
| public: | ||
| TestRefObj() : lChildren() {} | ||
| virtual ~TestRefObj() {} | ||
| virtual void Clear(Option_t *opt = "C") { lChildren.Clear(opt); } | ||
| virtual void SetChild(TestRefObj *aChild) { lChildren.Add(aChild); } | ||
| virtual const TestRefObj *GetChild(Int_t idx = 0) const { return static_cast<TestRefObj *>(lChildren.At(idx)); } | ||
| virtual Bool_t HasChild() const { return (lChildren.GetEntriesFast() > 0); } | ||
| ClassDef(TestRefObj, 1); | ||
| }; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #ifdef __CLING__ | ||
|
|
||
| #pragma link off all globals; | ||
| #pragma link off all classes; | ||
| #pragma link off all functions; | ||
|
|
||
| #pragma link C++ class TestRefObj+; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| #include "TObject.h" | ||
| #include "TestRefObj.h" | ||
| #include "TFile.h" | ||
| #include "TTree.h" | ||
| #include "TRandom.h" | ||
| #include "TClonesArray.h" | ||
| #include "TProcessID.h" | ||
| #include "TSystem.h" | ||
|
|
||
| #include "gtest/gtest.h" | ||
|
|
||
| // https://its.cern.ch/jira/browse/ROOT-7249 | ||
| TEST(TClonesArray, RefArrayClearChildren) | ||
| { | ||
| Bool_t resetObjectCount = kTRUE; | ||
| Bool_t activateBranchRef = kFALSE; | ||
| Int_t splitLevel = 1; | ||
| Bool_t pruneSecondChildren = kTRUE; | ||
| auto filename = "test7249.root"; | ||
| auto treename = "tree"; | ||
| // streamwithrefs | ||
| { | ||
| TFile testFile(filename, "RECREATE"); | ||
| TTree dataTree(treename, treename); | ||
|
|
||
| TClonesArray particles(TestRefObj::Class(), 100); | ||
| TClonesArray children(TestRefObj::Class(), 100); | ||
|
|
||
| dataTree.Branch("particles", &particles, 32768, splitLevel); | ||
| dataTree.Branch("children", &children, 32768, splitLevel); | ||
| if (activateBranchRef) { | ||
| dataTree.BranchRef(); | ||
| } | ||
|
|
||
| for (Int_t e = 0; e < 1000; e++) { | ||
| // For each "event". | ||
| UInt_t objCount = TProcessID::GetObjectCount(); | ||
|
|
||
| TestRefObj *motherPart = static_cast<TestRefObj *>(particles.ConstructedAt(0)); | ||
| TestRefObj *childPart = static_cast<TestRefObj *>(children.ConstructedAt(0)); | ||
| motherPart->SetChild(childPart); | ||
|
|
||
| // Prune all children if requested and event odd. | ||
| if (pruneSecondChildren && (e % 2 != 0)) { | ||
| children.Clear("C"); | ||
| } | ||
|
|
||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @olifre could you explain at this line how your "second workaround" was working? I guess that, before calling dataTree.Fill(), you were walking in a for-loop the motherPart.GetChild() checking whether the stored process ID still existed in the static TProcess table ?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ferdymercury Actually, since this was in an experiment-specific framework and I did not trust all users to do it right, I chose the following approach:
void CBTRefArray::fMaybePruned() {
for (Int_t i = 0; i < fSize; i++) {
if (fUIDs[i]) {
/* Re-check reference-target, might have become NULL due to pruning -
* in that case, store that in our UniqueID.
*/
if (At(i) == nullptr) {
fUIDs[i] = 0;
}
}
}
}(and the same without loop for So in the end, it was the loop you described, but actually the
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! A bit related issue: https://its.cern.ch/jira/browse/ROOT-6077 |
||
| dataTree.Fill(); | ||
|
|
||
| children.Clear("C"); | ||
| particles.Clear("C"); | ||
|
|
||
| if (resetObjectCount) { | ||
| TProcessID::SetObjectCount(objCount); | ||
| } | ||
| } | ||
| dataTree.Write(); | ||
| testFile.Close(); | ||
| } | ||
| // readwithrefs | ||
| { | ||
| TFile testFile(filename, "READ"); | ||
| TTree *dataTree = testFile.Get<TTree>(treename); | ||
|
|
||
| TClonesArray *particles = nullptr; | ||
| TClonesArray *children = nullptr; | ||
|
|
||
| dataTree->SetBranchAddress("particles", &particles); | ||
| dataTree->SetBranchAddress("children", &children); | ||
|
|
||
| if (activateBranchRef) { | ||
| dataTree->BranchRef(); | ||
| } | ||
| const Long64_t entries = dataTree->GetEntriesFast(); | ||
| for (Long64_t e = 0; e < entries; e++) { | ||
| dataTree->GetEntry(e); | ||
|
|
||
| // For each "event". | ||
| UInt_t objCount = TProcessID::GetObjectCount(); | ||
|
|
||
| // UInt_t parts = particles->GetEntries(); | ||
| UInt_t childs = children->GetEntries(); | ||
|
|
||
| auto parti = static_cast<TestRefObj *>(particles->UncheckedAt(0)); | ||
| if (pruneSecondChildren && (e % 2 != 0)) { | ||
| ASSERT_EQ(childs, 0); | ||
| ASSERT_FALSE(parti->HasChild()); | ||
| } else { | ||
| ASSERT_NE(childs, 0); | ||
| ASSERT_TRUE(parti->HasChild()); | ||
| } | ||
|
|
||
| children->Clear("C"); | ||
| particles->Clear("C"); | ||
|
|
||
| if (resetObjectCount) { | ||
| TProcessID::SetObjectCount(objCount); | ||
| } | ||
| } | ||
|
|
||
| delete dataTree; | ||
| testFile.Close(); | ||
| } | ||
| gSystem->Unlink(filename); | ||
| } | ||
|
|
||
| // https://its.cern.ch/jira/browse/ROOT-7473 | ||
| TEST(TClonesArray, ClearSlot) | ||
| { | ||
| TClonesArray particles(TestRefObj::Class(), 100); | ||
| TClonesArray children(TestRefObj::Class(), 100); | ||
| TestRefObj *motherPart = static_cast<TestRefObj *>(particles.ConstructedAt(0)); | ||
| TestRefObj *childPart = static_cast<TestRefObj *>(children.ConstructedAt(0)); | ||
| motherPart->SetChild(childPart); | ||
| particles.ClearSlot(0, "C"); | ||
| auto parti = static_cast<TestRefObj *>(particles.UncheckedAt(0)); | ||
| ASSERT_EQ(parti, nullptr); | ||
| auto child = static_cast<TestRefObj *>(children.UncheckedAt(0)); | ||
| ASSERT_NE(child, nullptr); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.