Skip to content

Commit

Permalink
EventSetupRecord::doGet uses prefetching
Browse files Browse the repository at this point in the history
Changed EventSetupRecord::doGet to work with prefetching. This required the introduction of ESGetTokenGeneric and a new esConsumes method.
Added the EDConsumerBase::registerLateConsumes to be able to safely call esConsumes based on the contents of the EventSetup.
  • Loading branch information
Dr15Jones committed Oct 13, 2020
1 parent 260347d commit d3dd43b
Show file tree
Hide file tree
Showing 14 changed files with 296 additions and 177 deletions.
5 changes: 0 additions & 5 deletions FWCore/Framework/interface/DataProxy.h
Expand Up @@ -51,11 +51,6 @@ namespace edm {
void prefetchAsync(
WaitingTask*, EventSetupRecordImpl const&, DataKey const&, EventSetupImpl const*, ServiceToken const&) const;

void doGet(EventSetupRecordImpl const&,
DataKey const&,
bool iTransiently,
ActivityRegistry const*,
EventSetupImpl const*) const;
void const* get(EventSetupRecordImpl const&,
DataKey const&,
bool iTransiently,
Expand Down
10 changes: 10 additions & 0 deletions FWCore/Framework/interface/EDConsumerBase.h
Expand Up @@ -39,6 +39,7 @@
#include "FWCore/Utilities/interface/InputTag.h"
#include "FWCore/Utilities/interface/EDGetToken.h"
#include "FWCore/Utilities/interface/ESGetToken.h"
#include "FWCore/Utilities/interface/ESGetTokenGeneric.h"
#include "FWCore/Utilities/interface/ESInputTag.h"
#include "FWCore/Utilities/interface/SoATuple.h"
#include "FWCore/Utilities/interface/Transition.h"
Expand Down Expand Up @@ -222,7 +223,16 @@ namespace edm {
return EDConsumerBaseWithTagESAdaptor<Tr>(this, std::move(tag));
}

///Used with EventSetupRecord::doGet
template <Transition Tr = Transition::Event>
ESGetTokenGeneric esConsumes(eventsetup::EventSetupRecordKey const& iRecord, eventsetup::DataKey const& iKey) {
return ESGetTokenGeneric(static_cast<unsigned int>(Tr),
recordESConsumes(Tr, iRecord, iKey.type(), ESInputTag("", iKey.name().value())),
iRecord.type());
}

private:
virtual void registerLateConsumes(eventsetup::ESRecordsToProxyIndices const&) {}
unsigned int recordConsumes(BranchType iBranch, TypeToGet const& iType, edm::InputTag const& iTag, bool iAlwaysGets);
ESTokenIndex recordESConsumes(Transition,
eventsetup::EventSetupRecordKey const&,
Expand Down
6 changes: 6 additions & 0 deletions FWCore/Framework/interface/ESRecordsToProxyIndices.h
Expand Up @@ -51,6 +51,12 @@ namespace edm::eventsetup {
}

ESRecordIndex recordIndexFor(EventSetupRecordKey const& iRK) const noexcept;

std::pair<std::vector<DataKey>::const_iterator, std::vector<DataKey>::const_iterator> keysForRecord(
EventSetupRecordKey const& iRK) const noexcept;
///The sorted list of keys
std::vector<EventSetupRecordKey> recordKeys() const noexcept { return recordKeys_; }

// ---------- member functions ---------------------------
///This should be called for all records in the list passed to the constructor and
/// in the same order as the list.
Expand Down
3 changes: 2 additions & 1 deletion FWCore/Framework/interface/EventSetupRecord.h
Expand Up @@ -45,6 +45,7 @@
#include "FWCore/Framework/interface/ValidityInterval.h"
#include "FWCore/Framework/interface/EventSetupRecordImpl.h"
#include "FWCore/Utilities/interface/ESGetToken.h"
#include "FWCore/Utilities/interface/ESGetTokenGeneric.h"
#include "FWCore/Utilities/interface/ESInputTag.h"
#include "FWCore/Utilities/interface/ESIndices.h"
#include "FWCore/Utilities/interface/Likely.h"
Expand Down Expand Up @@ -155,7 +156,7 @@ namespace edm {
}

///returns false if no data available for key
bool doGet(DataKey const& aKey, bool aGetTransiently = false) const;
bool doGet(ESGetTokenGeneric const&, bool aGetTransiently = false) const;

/**returns true only if someone has already requested data for this key
and the data was retrieved
Expand Down
4 changes: 0 additions & 4 deletions FWCore/Framework/interface/EventSetupRecordImpl.h
Expand Up @@ -85,10 +85,6 @@ namespace edm {

ValidityInterval validityInterval() const;

///returns false if no data available for key
bool doGet(DataKey const& aKey, EventSetupImpl const*, bool aGetTransiently = false) const;
bool doGet(ESProxyIndex iProxyIndex, EventSetupImpl const*, bool aGetTransiently = false) const;

///prefetch the data to setup for subsequent calls to getImplementation
void prefetchAsync(WaitingTask* iTask, ESProxyIndex iProxyIndex, EventSetupImpl const*, ServiceToken const&) const;

Expand Down
8 changes: 0 additions & 8 deletions FWCore/Framework/src/DataProxy.cc
Expand Up @@ -115,13 +115,5 @@ namespace edm {
return getAfterPrefetch(iRecord, iKey, iTransiently);
}

void DataProxy::doGet(const EventSetupRecordImpl& iRecord,
const DataKey& iKey,
bool iTransiently,
ActivityRegistry const* activityRegistry,
EventSetupImpl const* iEventSetupImpl) const {
get(iRecord, iKey, iTransiently, activityRegistry, iEventSetupImpl);
}

} // namespace eventsetup
} // namespace edm
2 changes: 2 additions & 0 deletions FWCore/Framework/src/EDConsumerBase.cc
Expand Up @@ -193,6 +193,8 @@ void EDConsumerBase::updateLookup(BranchType iBranchType,
}

void EDConsumerBase::updateLookup(eventsetup::ESRecordsToProxyIndices const& iPI) {
registerLateConsumes(iPI);

unsigned int index = 0;
for (auto it = m_esTokenInfo.begin<kESLookupInfo>(); it != m_esTokenInfo.end<kESLookupInfo>(); ++it, ++index) {
auto indexInRecord = iPI.indexInRecord(it->m_record, it->m_key);
Expand Down
15 changes: 13 additions & 2 deletions FWCore/Framework/src/ESRecordsToProxyIndices.cc
Expand Up @@ -47,8 +47,8 @@ namespace edm::eventsetup {
//
// const member functions
//
ESProxyIndex ESRecordsToProxyIndices::indexInRecord(EventSetupRecordKey const& iRK, DataKey const& iDK) const
noexcept {
ESProxyIndex ESRecordsToProxyIndices::indexInRecord(EventSetupRecordKey const& iRK,
DataKey const& iDK) const noexcept {
auto it = std::lower_bound(recordKeys_.begin(), recordKeys_.end(), iRK);
if (it == recordKeys_.end() or *it != iRK) {
return missingProxyIndex();
Expand Down Expand Up @@ -123,4 +123,15 @@ namespace edm::eventsetup {
return returnValue;
}

std::pair<std::vector<DataKey>::const_iterator, std::vector<DataKey>::const_iterator>
ESRecordsToProxyIndices::keysForRecord(EventSetupRecordKey const& iRK) const noexcept {
auto recIndex = recordIndexFor(iRK);
if (recIndex == missingRecordIndex()) {
return std::make_pair(dataKeys_.end(), dataKeys_.end());
}
auto const beginIndex = recordOffsets_[recIndex.value()];
auto const endIndex = recordOffsets_[recIndex.value() + 1];
return std::make_pair(dataKeys_.begin() + beginIndex, dataKeys_.begin() + endIndex);
}

} // namespace edm::eventsetup
24 changes: 22 additions & 2 deletions FWCore/Framework/src/EventSetupRecord.cc
Expand Up @@ -20,6 +20,13 @@

#include "FWCore/Utilities/interface/Exception.h"

namespace {
void throwWrongRecordType(const edm::TypeIDBase& aFromToken, const edm::eventsetup::EventSetupRecordKey& aRecord) {
throw cms::Exception("WrongRecordType") << "A ESGetTokenGeneric token using the record " << aFromToken.name()
<< " was passed to record " << aRecord.type().name();
}
} // namespace

namespace edm {
namespace eventsetup {

Expand All @@ -29,8 +36,21 @@ namespace edm {

EventSetupRecord::~EventSetupRecord() {}

bool EventSetupRecord::doGet(const DataKey& aKey, bool aGetTransiently) const {
return impl_->doGet(aKey, eventSetupImpl_, aGetTransiently);
bool EventSetupRecord::doGet(const ESGetTokenGeneric& aToken, bool aGetTransiently) const {
if UNLIKELY (aToken.transitionID() != transitionID()) {
throwWrongTransitionID();
}
if UNLIKELY (aToken.recordType() != key().type()) {
throwWrongRecordType(aToken.recordType(), key());
}
auto proxyIndex = getTokenIndices_[aToken.index().value()];
if UNLIKELY (proxyIndex.value() == std::numeric_limits<int>::max()) {
return false;
}

const ComponentDescription* cd = nullptr;
DataKey const* dk = nullptr;
return nullptr != impl_->getFromProxyAfterPrefetch(proxyIndex, aGetTransiently, cd, dk);
}

bool EventSetupRecord::wasGotten(const DataKey& aKey) const { return impl_->wasGotten(aKey); }
Expand Down
43 changes: 0 additions & 43 deletions FWCore/Framework/src/EventSetupRecordImpl.cc
Expand Up @@ -257,49 +257,6 @@ namespace edm {
return proxies_[std::distance(keysForProxies_.begin(), lb)].get();
}

bool EventSetupRecordImpl::doGet(const DataKey& aKey,
EventSetupImpl const* iEventSetupImpl,
bool aGetTransiently) const {
const DataProxy* proxy = find(aKey);
if (nullptr != proxy) {
try {
convertException::wrap(
[&]() { proxy->doGet(*this, aKey, aGetTransiently, activityRegistry_, iEventSetupImpl); });
} catch (cms::Exception& e) {
addTraceInfoToCmsException(e, aKey.name().value(), proxy->providerDescription(), aKey);
//NOTE: the above function can't do the 'throw' since it causes the C++ class type
// of the throw to be changed, a 'rethrow' does not have that problem
throw;
}
}
return nullptr != proxy;
}

bool EventSetupRecordImpl::doGet(ESProxyIndex iProxyIndex,
EventSetupImpl const* iEventSetupImpl,
bool aGetTransiently) const {
if UNLIKELY (iProxyIndex.value() == std::numeric_limits<int>::max()) {
return false;
}

const DataProxy* proxy = proxies_[iProxyIndex.value()];
if (nullptr != proxy) {
try {
convertException::wrap([&]() {
auto const& key = keysForProxies_[iProxyIndex.value()];
proxy->doGet(*this, key, aGetTransiently, activityRegistry_, iEventSetupImpl);
});
} catch (cms::Exception& e) {
auto const& key = keysForProxies_[iProxyIndex.value()];
addTraceInfoToCmsException(e, key.name().value(), proxy->providerDescription(), key);
//NOTE: the above function can't do the 'throw' since it causes the C++ class type
// of the throw to be changed, a 'rethrow' does not have that problem
throw;
}
}
return nullptr != proxy;
}

void EventSetupRecordImpl::prefetchAsync(WaitingTask* iTask,
ESProxyIndex iProxyIndex,
EventSetupImpl const* iEventSetupImpl,
Expand Down
103 changes: 74 additions & 29 deletions FWCore/Framework/test/eventsetuprecord_t.cppunit.cc
Expand Up @@ -265,19 +265,42 @@ namespace {

ESGetToken<Dummy, DummyRecord> m_token;
};

struct DummyDataConsumerGeneric : public EDConsumerBase {
explicit DummyDataConsumerGeneric(DataKey const& iKey)
: m_token{esConsumes<>(eventsetup::EventSetupRecordKey::makeKey<DummyRecord>(), iKey)} {}

void prefetch(eventsetup::EventSetupRecordImpl const& iRec) const {
auto const& proxies = this->esGetTokenIndicesVector(edm::Transition::Event);
for (size_t i = 0; i != proxies.size(); ++i) {
auto waitTask = edm::make_empty_waiting_task();
waitTask->set_ref_count(2);
iRec.prefetchAsync(waitTask.get(), proxies[i], nullptr, edm::ServiceToken{});
waitTask->decrement_ref_count();
waitTask->wait_for_all();
if (waitTask->exceptionPtr()) {
std::rethrow_exception(*waitTask->exceptionPtr());
}
}
}

ESGetTokenGeneric m_token;
};

} // namespace

namespace {
struct SetupRecord {
template <typename CONSUMER>
struct SetupRecordT {
eventsetup::EventSetupRecordImpl dummyRecordImpl;
DummyDataConsumer& consumer;
CONSUMER& consumer;
//we need the DataKeys to stick around since references are being kept to them
std::vector<std::pair<edm::eventsetup::DataKey, edm::eventsetup::DataProxy*>> proxies;

SetupRecord(DummyDataConsumer& iConsumer,
EventSetupRecordKey const& iKey,
ActivityRegistry* iRegistry,
std::vector<std::pair<edm::eventsetup::DataKey, edm::eventsetup::DataProxy*>> iProxies)
SetupRecordT(CONSUMER& iConsumer,
EventSetupRecordKey const& iKey,
ActivityRegistry* iRegistry,
std::vector<std::pair<edm::eventsetup::DataKey, edm::eventsetup::DataProxy*>> iProxies)
: dummyRecordImpl(iKey, iRegistry), consumer(iConsumer), proxies(std::move(iProxies)) {
for (auto const& d : proxies) {
dummyRecordImpl.add(d.first, d.second);
Expand All @@ -299,6 +322,8 @@ namespace {
return ret;
}
};
using SetupRecord = SetupRecordT<DummyDataConsumer>;
using SetupGenericRecord = SetupRecordT<DummyDataConsumerGeneric>;
} // namespace

void testEventsetupRecord::getHandleTest() {
Expand Down Expand Up @@ -504,29 +529,42 @@ void testEventsetupRecord::getExepTest() {
}

void testEventsetupRecord::doGetTest() {
eventsetup::EventSetupRecordImpl dummyRecordImpl{dummyRecordKey_, &activityRegistry};
const DataKey dummyDataKey(DataKey::makeTypeTag<FailingDummyProxy::value_type>(), "");

FailingDummyProxy dummyProxy;
{
DummyDataConsumerGeneric consumer{dummyDataKey};

const DataKey dummyDataKey(DataKey::makeTypeTag<FailingDummyProxy::value_type>(), "");
SetupGenericRecord sr{consumer, dummyRecordKey_, &activityRegistry, {}};

DummyRecord dummyRecord;
dummyRecord.setImpl(&dummyRecordImpl, 0, nullptr, nullptr, false);
CPPUNIT_ASSERT(!dummyRecord.doGet(dummyDataKey));
DummyRecord dummyRecord = sr.makeRecord();

dummyRecordImpl.add(dummyDataKey, &dummyProxy);
CPPUNIT_ASSERT(!dummyRecord.doGet(consumer.m_token));
}

FailingDummyProxy dummyProxy;

{
DummyDataConsumerGeneric consumer{dummyDataKey};

//dummyRecord.doGet(dummyDataKey);
CPPUNIT_ASSERT_THROW(dummyRecord.doGet(dummyDataKey), ExceptionType);
SetupGenericRecord sr{consumer, dummyRecordKey_, &activityRegistry, {{dummyDataKey, &dummyProxy}}};

DummyRecord dummyRecord = sr.makeRecord();
CPPUNIT_ASSERT_THROW(dummyRecord.doGet(consumer.m_token), ExceptionType);
}
Dummy myDummy;
WorkingDummyProxy workingProxy(&myDummy);

const DataKey workingDataKey(DataKey::makeTypeTag<WorkingDummyProxy::value_type>(), "working");

dummyRecordImpl.add(workingDataKey, &workingProxy);
{
DummyDataConsumerGeneric consumer{workingDataKey};

CPPUNIT_ASSERT(dummyRecord.doGet(workingDataKey));
SetupGenericRecord sr{
consumer, dummyRecordKey_, &activityRegistry, {{dummyDataKey, &dummyProxy}, {workingDataKey, &workingProxy}}};

DummyRecord dummyRecord = sr.makeRecord();
CPPUNIT_ASSERT(dummyRecord.doGet(consumer.m_token));
}
}

namespace {
Expand Down Expand Up @@ -662,21 +700,30 @@ void testEventsetupRecord::introspectionTest() {
}

void testEventsetupRecord::doGetExepTest() {
eventsetup::EventSetupRecordImpl dummyRecordImpl{dummyRecordKey_, &activityRegistry};
const DataKey dummyDataKey(DataKey::makeTypeTag<FailingDummyProxy::value_type>(), "");
{
DummyDataConsumerGeneric consumer{dummyDataKey};

FailingDummyProxy dummyProxy;
SetupGenericRecord sr{consumer, dummyRecordKey_, &activityRegistry, {}};

const DataKey dummyDataKey(DataKey::makeTypeTag<FailingDummyProxy::value_type>(), "");
DummyRecord dummyRecord = sr.makeRecord();

DummyRecord dummyRecord;
dummyRecord.setImpl(&dummyRecordImpl, 0, nullptr, nullptr, false);
CPPUNIT_ASSERT(!dummyRecord.doGet(dummyDataKey));
CPPUNIT_ASSERT(!dummyRecord.doGet(consumer.m_token));
}

dummyRecordImpl.add(dummyDataKey, &dummyProxy);
{
FailingDummyProxy dummyProxy;

//typedef edm::eventsetup::MakeDataException<DummyRecord,Dummy> ExceptionType;
dummyRecord.doGet(dummyDataKey);
//CPPUNIT_ASSERT_THROW(dummyRecord.doGet(dummyDataKey), ExceptionType);
const DataKey dummyDataKey(DataKey::makeTypeTag<FailingDummyProxy::value_type>(), "");

DummyDataConsumerGeneric consumer{dummyDataKey};

SetupGenericRecord sr{consumer, dummyRecordKey_, &activityRegistry, {{dummyDataKey, &dummyProxy}}};

DummyRecord dummyRecord = sr.makeRecord();

CPPUNIT_ASSERT(dummyRecord.doGet(consumer.m_token));
}
}

void testEventsetupRecord::proxyResetTest() {
Expand All @@ -703,8 +750,6 @@ void testEventsetupRecord::proxyResetTest() {
edm::eventsetup::EventSetupRecordProvider::DataToPreferredProviderMap pref;
dummyProvider->usePreferred(pref);

CPPUNIT_ASSERT(dummyRecord.doGet(workingDataKey));

edm::ESHandle<Dummy> hDummy;
dummyRecord.get(hDummy);

Expand Down

0 comments on commit d3dd43b

Please sign in to comment.