diff --git a/FWCore/Framework/interface/Callback.h b/FWCore/Framework/interface/Callback.h index c92ad22c5595f..5cd6020044dcc 100644 --- a/FWCore/Framework/interface/Callback.h +++ b/FWCore/Framework/interface/Callback.h @@ -20,6 +20,7 @@ // system include files #include +#include // user include files #include "FWCore/Framework/interface/produce_helpers.h" #include "FWCore/Utilities/interface/propagate_const.h" @@ -47,12 +48,12 @@ namespace edm { =CallbackSimpleDecorator > class Callback : public CallbackBase { public: - typedef TReturn (T ::* method_type)(const TRecord&); + using method_type = TReturn (T ::*)(const TRecord&); Callback(T* iProd, method_type iMethod, const TDecorator& iDec = TDecorator()) : - proxyData_(produce::size< TReturn >::value, static_cast(nullptr)), + proxyData_{}, producer_(iProd), method_(iMethod), wasCalledForThisRecord_(false), @@ -82,23 +83,18 @@ namespace edm { void storeReturnedValues(TReturn iReturn) { //std::cout <<" storeReturnedValues "<< iReturn <<" " <value_ <::type type; - setData(iReturn, static_cast(nullptr), static_cast(nullptr)); + using type = typename produce::product_traits::type; + setData(iReturn); } template - void setData(ProductsT& iProducts, const RemainingContainerT*, const DataT*) { + void setData(ProductsT& iProducts) { DataT* temp = reinterpret_cast< DataT*>(proxyData_[produce::find_index::value]) ; - if(nullptr != temp) { copyFromTo(iProducts, *temp); } - setData(iProducts, static_cast< const typename RemainingContainerT::head_type *>(nullptr), - static_cast< const typename RemainingContainerT::tail_type *>(nullptr)); - } - template - void setData(ProductsT& iProducts, const produce::Null*, const DataT*) { - - DataT* temp = reinterpret_cast< DataT*>(proxyData_[produce::find_index::value]) ; - //std::cout <<" setData["<< produce::find_index::value<<"] "<< temp < ) { + setData(iProducts); + } } void newRecordComing() { wasCalledForThisRecord_ = false; @@ -109,7 +105,7 @@ namespace edm { const Callback& operator=(const Callback&) = delete; // stop default - std::vector proxyData_; + std::array::value> proxyData_; edm::propagate_const producer_; method_type method_; bool wasCalledForThisRecord_; diff --git a/FWCore/Framework/interface/CallbackProxy.h b/FWCore/Framework/interface/CallbackProxy.h index ed94cdab856f3..e8a8b56ed2c42 100644 --- a/FWCore/Framework/interface/CallbackProxy.h +++ b/FWCore/Framework/interface/CallbackProxy.h @@ -38,8 +38,9 @@ namespace edm { class CallbackProxy : public DataProxy { public: - typedef typename produce::smart_pointer_traits::type value_type; - typedef RecordT record_type; + using smart_pointer_traits = produce::smart_pointer_traits; + using value_type = typename smart_pointer_traits::type; + using record_type = RecordT; CallbackProxy(std::shared_ptr& iCallback) : data_(), @@ -62,7 +63,7 @@ namespace edm { record_type rec; rec.setImpl(&iRecord); (*callback_)(rec); - return &(*data_); + return smart_pointer_traits::getPointer(data_); } void invalidateCache() override { diff --git a/FWCore/Framework/interface/ESProducts.h b/FWCore/Framework/interface/ESProducts.h index 1f6e02534666a..f4e94c4957a07 100644 --- a/FWCore/Framework/interface/ESProducts.h +++ b/FWCore/Framework/interface/ESProducts.h @@ -12,7 +12,7 @@ Usage: This is used as a return type from the produce method of an ESProducer. Users are not anticipated to ever need to directly use this class. Instead, to create an instance of the class at method return time, they should call - the helper function es::products or 'output' the values to es::produced via the '<<' operator. + the helper function es::products. */ // @@ -30,93 +30,26 @@ namespace edm { namespace eventsetup { namespace produce { - struct Produce { - Produce() {} - }; - - template< typename T> struct OneHolder { - OneHolder() {} - OneHolder(const T& iValue) : value_(iValue) {} - - template - void setFromRecursive(S& iGiveValues) { - iGiveValues.setFrom(value_); - } - - void assignTo(T& oValue) { oValue = value_;} - T value_; - typedef T tail_type; - typedef Null head_type; - }; - - template struct OneHolder> { - typedef std::unique_ptr Type; - OneHolder() {} - OneHolder(OneHolder const& iOther): value_(const_cast&>(iOther).value_) {} - OneHolder(Type iPtr): value_(iPtr) {} - - - OneHolder const& operator=(OneHolder iRHS) { value_ = iRHS.value_; return *this; } - template - void setFromRecursive(S& iGiveValues) { - iGiveValues.setFrom(value_); - } - - void assignTo(Type& oValue) { oValue = value_;} - mutable Type value_; //mutable needed for std::unique_ptr - typedef Type tail_type; - typedef Null head_type; - }; - - template OneHolder operator<<(const Produce&, T iValue) { - return OneHolder(iValue); - } - - template struct MultiHolder { - MultiHolder(const T& iT, U iValue): value_(iValue), head_(iT) { - } - - template - void setFromRecursive(TTaker& iGiveValues) { - iGiveValues.setFrom(value_); - head_.setFromRecursive(iGiveValues); - } - - - void assignTo(U& oValue) { oValue = value_;} - U value_; - T head_; - - typedef U tail_type; - typedef T head_type; - }; - - template - MultiHolder, S> operator<<(const OneHolder& iHolder, - const S& iValue) { - return MultiHolder, S>(iHolder, iValue); - } - template< typename T, typename U, typename V> - MultiHolder< MultiHolder, V > - operator<<(const MultiHolder& iHolder, const V& iValue) { - return MultiHolder< MultiHolder, V> (iHolder, iValue); - } - - template - struct ProductHolder : public ProductHolder { - typedef ProductHolder parent_type; + template + struct ProductHolder : public ProductHolder { + using parent_type = ProductHolder; ProductHolder() : value() {} - + ProductHolder(ProductHolder&&) = default; + ProductHolder(ProductHolder const&) = default; + ProductHolder& operator=(ProductHolder&&) = default; + ProductHolder& operator=(ProductHolder const&) = default; + template void setAllValues(T& iValuesFrom) { iValuesFrom.setFromRecursive(*this); } - using parent_type::assignTo; - void assignTo(T1& oValue) { oValue = value; } + using parent_type::moveTo; + void moveTo(T1& oValue) { oValue = std::move(value); } using parent_type::setFrom; void setFrom(T1& iValue) { value = iValue ; } + void setFrom(T1&& iValue) { value = std::move(iValue) ; } template void setFromRecursive(T& iValuesTo) { @@ -125,30 +58,35 @@ namespace edm { } template - void assignToRecursive(T& iValuesTo) { - iValuesTo.assignTo(value); - parent_type::assignToRecursive(iValuesTo); + void moveToRecursive(T& iValuesTo) { + iValuesTo.moveTo(value); + parent_type::moveToRecursive(iValuesTo); } T1 value; - typedef T1 tail_type; - typedef parent_type head_type; + using tail_type = T1; + using head_type = parent_type; }; template - struct ProductHolder { + struct ProductHolder { ProductHolder() : value() {} + ProductHolder(ProductHolder&&) = default; + ProductHolder(ProductHolder const&) = default; + ProductHolder& operator=(ProductHolder&&) = default; + ProductHolder& operator=(ProductHolder const&) = default; template void setAllValues(T& iValuesFrom) { - iValuesFrom.assignToRecursive(*this); + iValuesFrom.moveToRecursive(*this); } - void assignTo(T1& oValue) { oValue = value; } + void moveTo(T1& oValue) { oValue = std::move(value); } void setFrom(T1& iValue) { value = iValue ; } + void setFrom(T1&& iValue) { value = std::move(iValue) ; } template - void assignToRecursive(T& iValuesTo) { - iValuesTo.assignTo(value); + void moveToRecursive(T& iValuesTo) { + iValuesTo.moveTo(value); } template void setFromRecursive(T& iValuesTo) { @@ -156,52 +94,47 @@ namespace edm { } T1 value; - typedef T1 tail_type; - typedef Null head_type; + using tail_type = T1; + using head_type = Null; }; - template<> - struct ProductHolder { - void setAllValues(Null&) {} - void assignTo(void*) {} - void setFrom(void*) {} - - typedef Null tail_type; - typedef Null head_type; - }; } } - template - struct ESProducts : public eventsetup::produce::ProductHolder { - typedef eventsetup::produce::ProductHolder parent_type; - template - ESProducts(const ESProducts& iProducts) { - parent_type::setAllValues(const_cast&>(iProducts)); + struct ESFillDirectly {}; + + template + struct ESProducts : public eventsetup::produce::ProductHolder { + typedef eventsetup::produce::ProductHolder parent_type; + template + ESProducts(ESProducts&& iProducts) { + parent_type::setAllValues(iProducts); } template - /*explicit*/ ESProducts(const T& iValues) { - parent_type::setAllValues(const_cast(iValues)); + /*explicit*/ ESProducts(T&& iValues) { + parent_type::setAllValues(iValues); + } + template + ESProducts(ESFillDirectly, Vars&&... vars) { + (this->setFrom(std::forward(vars)), ...); } + + ESProducts(ESProducts const&) = default; + ESProducts(ESProducts&&) = default; + ESProducts& operator=(ESProducts const&) = default; + ESProducts& operator=(ESProducts&&) = default; }; namespace es { - extern const eventsetup::produce::Produce produced; - - template - ESProducts products(const T& i1, const S& i2) { - return ESProducts(produced << i1 << i2); + template + ESProducts...> products(TArgs&&... args) { + return ESProducts...>(edm::ESFillDirectly{}, std::forward(args)...); } - - template - ESProducts products(const T& i1, const S& i2, const U& i3) { - return ESProducts(produced << i1 << i2 << i3); - } } - template - void copyFromTo(ESProducts& iFrom, + template + void moveFromTo(ESProducts& iFrom, ToT& iTo) { - iFrom.assignTo(iTo); + iFrom.moveTo(iTo); } } diff --git a/FWCore/Framework/interface/produce_helpers.h b/FWCore/Framework/interface/produce_helpers.h index 20ac09d188e9a..23b312043dcc9 100644 --- a/FWCore/Framework/interface/produce_helpers.h +++ b/FWCore/Framework/interface/produce_helpers.h @@ -20,6 +20,7 @@ // system include files #include +#include // user include files // forward declarations @@ -28,76 +29,75 @@ namespace edm { namespace produce { struct Null;} - template void copyFromTo(FromT& iFrom, + template void moveFromTo(FromT& iFrom, ToT & iTo) { - iTo = iFrom; + iTo = std::move(iFrom); } - template void copyFromTo(std::unique_ptr& iFrom, ToT & iTo) { + template void moveFromTo(std::unique_ptr& iFrom, ToT & iTo) { iTo = std::move(iFrom); } + template void moveFromTo(std::optional& iFrom, ToT & iTo) { + iTo = std::move(iFrom.value()); + } namespace produce { struct Null {}; template struct EndList { static_assert( (not std::is_pointer_v) ,"use std::shared_ptr or std::unique_ptr to hold EventSetup data products, do not use bare pointers"); - typedef T tail_type; - typedef Null head_type; + using tail_type = T; + using head_type = Null; }; template struct product_traits { - typedef T type; + using type = T; }; template< typename T> struct product_traits { - typedef EndList type; + using type = EndList; }; template< typename T> struct product_traits > { - typedef EndList > type; + using type= EndList>; }; template< typename T> struct product_traits > { - typedef EndList > type; + using type = EndList>; + }; + template< typename T> struct product_traits > { + using type=EndList>; }; - template struct size { - typedef typename product_traits::type type; - enum { value = size< typename type::head_type >::value + 1 }; + using type = typename product_traits::type; + constexpr static int value = size< typename type::head_type >::value + 1; }; template<> struct size { - enum { value = 0 }; + constexpr static int value = 0; }; template struct smart_pointer_traits { - typedef typename T::element_type type; + using type = typename T::element_type; + static auto getPointer(T& iPtr)-> decltype(&*iPtr) { return &*iPtr;} }; - - template struct smart_pointer_traits { - typedef T type; - }; - template struct smart_pointer_traits< T const *> { - typedef T type; + + template struct smart_pointer_traits> { + using type = T; + static T* getPointer(std::optional& iPtr) { + if(iPtr.has_value()) { return &*iPtr;} + return nullptr; + } }; - - template void copyFromTo(FromT& iFrom, - ToT & iTo) { - iTo = iFrom; - } - - template void copyFromTo(std::unique_ptr& iFrom, ToT & iTo) { - iTo = std::move(iFrom); - } - - template struct find_index_impl { - typedef typename product_traits::type container_type; - enum { value = find_index_impl::value + 1 }; - }; - template struct find_index_impl { - enum { value = 0 }; - }; - template struct find_index { - typedef typename product_traits::type container_type; - enum {value = find_index_impl::value }; + using container_type = typename product_traits::type; + template + constexpr static int findIndexOf() { + if constexpr(not std::is_same_v) { + using container_type= typename product_traits::type; + return findIndexOf()+1; + } else { + return 0; + } + } + constexpr static int value = findIndexOf(); }; namespace test { template const char* name(const T*); diff --git a/FWCore/Framework/src/ESProducts.cc b/FWCore/Framework/src/ESProducts.cc deleted file mode 100644 index dfd534ca20b65..0000000000000 --- a/FWCore/Framework/src/ESProducts.cc +++ /dev/null @@ -1,22 +0,0 @@ -// -*- C++ -*- -// -// Package: Framework -// Class : ESProducts -// -// Implementation: -// -// -// Author: Chris Jones -// Created: Sun Apr 17 18:41:34 EDT 2005 -// - -// system include files - -// user include files -#include "FWCore/Framework/interface/ESProducts.h" - -namespace edm { - namespace es { - const eventsetup::produce::Produce produced; - } -} diff --git a/FWCore/Framework/test/DummyData.h b/FWCore/Framework/test/DummyData.h index 3440717d9a945..473e97bdc583f 100644 --- a/FWCore/Framework/test/DummyData.h +++ b/FWCore/Framework/test/DummyData.h @@ -17,8 +17,6 @@ namespace edm { struct DummyData { int value_; DummyData(int iValue=0) : value_(iValue) {} void dummy() {} // Just to suppress compilation warning message - private: - const DummyData& operator=(const DummyData&); }; } } diff --git a/FWCore/Framework/test/esproducer_t.cppunit.cc b/FWCore/Framework/test/esproducer_t.cppunit.cc index c3b3ff969f456..843b25d8f5169 100644 --- a/FWCore/Framework/test/esproducer_t.cppunit.cc +++ b/FWCore/Framework/test/esproducer_t.cppunit.cc @@ -36,6 +36,7 @@ CPPUNIT_TEST(registerTest); CPPUNIT_TEST(getFromTest); CPPUNIT_TEST(getfromShareTest); CPPUNIT_TEST(getfromUniqueTest); +CPPUNIT_TEST(getfromOptionalTest); CPPUNIT_TEST(decoratorTest); CPPUNIT_TEST(dependsOnTest); CPPUNIT_TEST(labelTest); @@ -51,6 +52,7 @@ CPPUNIT_TEST_SUITE_END(); void getFromTest(); void getfromShareTest(); void getfromUniqueTest(); + void getfromOptionalTest(); void decoratorTest(); void dependsOnTest(); void labelTest(); @@ -72,6 +74,20 @@ class Test1Producer : public ESProducer { DummyData data_; }; + class OptionalProducer : public ESProducer { + public: + OptionalProducer() : ESProducer(), data_() { + data_.value_ = 0; + setWhatProduced(this); + } + std::optional produce(const DummyRecord& /*iRecord*/) { + ++data_.value_; + return data_; + } + private: + DummyData data_; + }; + class MultiRegisterProducer : public ESProducer { public: MultiRegisterProducer() : ESProducer(), data_() { @@ -224,6 +240,27 @@ void testEsproducer::getfromUniqueTest() } } +void testEsproducer::getfromOptionalTest() +{ + EventSetupProvider provider(&activityRegistry); + + std::shared_ptr pProxyProv = std::make_shared(); + provider.add(pProxyProv); + + std::shared_ptr pFinder = std::make_shared(); + provider.add(std::shared_ptr(pFinder)); + + for(int iTime=1; iTime != 6; ++iTime) { + const edm::Timestamp time(iTime); + pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time) , edm::IOVSyncValue(time))); + const edm::EventSetup& eventSetup = provider.eventSetupForInstance(edm::IOVSyncValue(time)); + edm::ESHandle pDummy; + eventSetup.get().get(pDummy); + CPPUNIT_ASSERT(0 != pDummy.product()); + CPPUNIT_ASSERT(iTime == pDummy->value_); + } +} + void testEsproducer::labelTest() { try { diff --git a/FWCore/Framework/test/esproducts_t.cppunit.cc b/FWCore/Framework/test/esproducts_t.cppunit.cc index 3b8eb33c1e258..d2b1cdf116b9f 100644 --- a/FWCore/Framework/test/esproducts_t.cppunit.cc +++ b/FWCore/Framework/test/esproducts_t.cppunit.cc @@ -17,12 +17,16 @@ class testEsproducts: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(testEsproducts); CPPUNIT_TEST(constPtrTest); +CPPUNIT_TEST(uniquePtrTest); +CPPUNIT_TEST(sharedPtrTest); CPPUNIT_TEST(manyTest); CPPUNIT_TEST_SUITE_END(); public: void setUp(){} void tearDown(){} void constPtrTest(); + void uniquePtrTest(); + void sharedPtrTest(); void manyTest(); }; @@ -47,17 +51,55 @@ void testEsproducts::constPtrTest() const int* readInt = 0; const float* readFloat = 0; - product.assignTo(readInt); - product.assignTo(readFloat); + product.moveTo(readInt); + product.moveTo(readFloat); CPPUNIT_ASSERT(readInt == &int_); CPPUNIT_ASSERT(readFloat == &float_); } +void testEsproducts::uniquePtrTest() +{ + constexpr int kInt = 5; + auto int_ = std::make_unique(kInt); + constexpr float kFloat = 3.1; + auto float_ = std::make_unique(kFloat); + + ESProducts, std::unique_ptr> product = products(std::move(int_), std::move(float_)); + + std::unique_ptr readInt; + std::unique_ptr readFloat; + + product.moveTo(readInt); + product.moveTo(readFloat); + + CPPUNIT_ASSERT(*readInt == kInt); + CPPUNIT_ASSERT(*readFloat == kFloat); +} + +void testEsproducts::sharedPtrTest() +{ + auto int_ = std::make_shared(5); + auto float_ = std::make_shared(3.1); + + ESProducts, std::shared_ptr> product = + products(int_,float_); + + std::shared_ptr readInt; + std::shared_ptr readFloat; + + product.moveTo(readInt); + product.moveTo(readFloat); + + CPPUNIT_ASSERT(readInt.get() == int_.get()); + CPPUNIT_ASSERT(readFloat.get() == float_.get()); +} + + ESProducts returnManyPointers(const int* iInt, const float* iFloat, const double* iDouble) { - return edm::es::produced << iInt << iFloat << iDouble; + return edm::es::products(iInt, iFloat, iDouble); } void testEsproducts::manyTest() @@ -73,9 +115,9 @@ void testEsproducts::manyTest() const float* readFloat = 0; const double* readDouble = 0; - product.assignTo(readInt); - product.assignTo(readFloat); - product.assignTo(readDouble); + product.moveTo(readInt); + product.moveTo(readFloat); + product.moveTo(readDouble); CPPUNIT_ASSERT(readInt == &int_); CPPUNIT_ASSERT(readFloat == &float_);