Skip to content

Commit 6344955

Browse files
committed
Handle multiple threads reading RefCores
Deal with the case where the call to TTree::GetEntry uses multiple threads to de-serialize data from an Event.
1 parent 85670f3 commit 6344955

File tree

5 files changed

+46
-10
lines changed

5 files changed

+46
-10
lines changed

DataFormats/Common/interface/EDProductGetter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ namespace edm {
9797

9898
///These can only be used internally by the framework
9999
static EDProductGetter const* switchProductGetter(EDProductGetter const*);
100+
static void setMultiThreadProductGetter(EDProductGetter const*);
101+
static void unsetMultiThreadProductGetter();
100102
static void assignEDProductGetter(EDProductGetter const*&);
101103

102104
private:

DataFormats/Common/interface/RefCoreStreamer.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,15 @@ namespace edm {
4343
static void unsetRefCoreStreamer();
4444
static EDProductGetter const* setRefCoreStreamer(EDProductGetter const* ep);
4545
};
46+
class MultiThreadRefCoreStreamerGuard {
47+
public:
48+
MultiThreadRefCoreStreamerGuard(EDProductGetter const* ep) { setRefCoreStreamer(ep); }
49+
~MultiThreadRefCoreStreamerGuard() { unsetRefCoreStreamer(); }
50+
51+
private:
52+
static void setRefCoreStreamer(EDProductGetter const* ep);
53+
static void unsetRefCoreStreamer();
54+
};
55+
4656
} // namespace edm
4757
#endif

DataFormats/Common/src/EDProductGetter.cc

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
//
1212

1313
// system include files
14+
#include <atomic>
1415

1516
// user include files
1617
#include "DataFormats/Common/interface/EDProductGetter.h"
1718
#include "DataFormats/Provenance/interface/ProductID.h"
1819
#include "FWCore/Utilities/interface/EDMException.h"
20+
#include "FWCore/Utilities/interface/Likely.h"
1921

2022
namespace edm {
2123
//
@@ -75,16 +77,32 @@ namespace edm {
7577
}
7678

7779
thread_local EDProductGetter const* s_productGetter = nullptr;
80+
static std::atomic<EDProductGetter const*> s_multiThreadProductGetter{nullptr};
7881
EDProductGetter const* EDProductGetter::switchProductGetter(EDProductGetter const* iNew) {
7982
//std::cout <<"switch from "<<s_productGetter<<" to "<<iNew<<std::endl;
8083
EDProductGetter const* old = s_productGetter;
8184
s_productGetter = iNew;
8285
return old;
8386
}
87+
88+
void EDProductGetter::setMultiThreadProductGetter(EDProductGetter const* prodGetter) {
89+
EDProductGetter const* expected = nullptr;
90+
while( not s_multiThreadProductGetter.compare_exchange_strong(expected, prodGetter, std::memory_order_acq_rel)) {
91+
expected = nullptr;
92+
};
93+
}
94+
95+
void EDProductGetter::unsetMultiThreadProductGetter() {
96+
s_multiThreadProductGetter.store(nullptr, std::memory_order_release);
97+
}
98+
8499
void EDProductGetter::assignEDProductGetter(EDProductGetter const*& iGetter) {
85100
//std::cout <<"assign "<<s_productGetter<<std::endl;
86-
87-
iGetter = s_productGetter;
101+
if LIKELY (s_productGetter != nullptr) {
102+
iGetter = s_productGetter;
103+
return;
104+
}
105+
iGetter = s_multiThreadProductGetter.load(std::memory_order_acquire);
88106
}
89107

90108
} // namespace edm

DataFormats/Common/src/RefCoreStreamer.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,13 @@ namespace edm {
8989
}
9090
return returnValue;
9191
}
92+
93+
void MultiThreadRefCoreStreamerGuard::setRefCoreStreamer(EDProductGetter const* ep) {
94+
edm::EDProductGetter::setMultiThreadProductGetter(ep);
95+
}
96+
97+
void MultiThreadRefCoreStreamerGuard::unsetRefCoreStreamer() {
98+
edm::EDProductGetter::unsetMultiThreadProductGetter();
99+
}
100+
92101
} // namespace edm

IOPool/Input/src/RootPromptReadDelayedReader.cc

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,10 @@ namespace edm {
9999
branchInfo->productBranch_->SetAddress(&cache.wrapperBasePtr_);
100100
}
101101

102-
setRefCoreStreamer(ep);
103-
//make code exception safe
104-
std::shared_ptr<void> refCoreStreamerGuard(nullptr, [](void*) {
105-
setRefCoreStreamer(false);
106-
;
107-
});
108-
109-
tree_.getEntryForAllBranches();
102+
{
103+
// ROOT might use multiple threads while reading the entries
104+
MultiThreadRefCoreStreamerGuard epGuard(ep);
105+
tree_.getEntryForAllBranches();
106+
}
110107
}
111108
} // namespace edm

0 commit comments

Comments
 (0)