Skip to content

Commit

Permalink
Merge pull request #25707 from Dr15Jones/eventGetHandle
Browse files Browse the repository at this point in the history
Provide easier to use ::get and ::getHandle methods for Event, Run and LuminosityBlock
  • Loading branch information
cmsbuild authored Jan 23, 2019
2 parents 2710b89 + 6d31f49 commit fc4815a
Show file tree
Hide file tree
Showing 47 changed files with 530 additions and 331 deletions.
47 changes: 21 additions & 26 deletions DataFormats/Common/interface/BasicHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,82 +42,77 @@ namespace edm {

class BasicHandle {
public:
BasicHandle() :
product_(),
prov_(nullptr) {}
BasicHandle() = delete;

BasicHandle(BasicHandle const& h) :
product_(h.product_),
prov_(h.prov_),
whyFailedFactory_(h.whyFailedFactory_){}
BasicHandle(BasicHandle const& h) = default;

BasicHandle(BasicHandle &&h) = default;
BasicHandle(WrapperBase const* iProd, Provenance const* iProv) :

BasicHandle(WrapperBase const* iProd, Provenance const* iProv) noexcept(true):
product_(iProd),
prov_(iProv) {
}

///Used when the attempt to get the data failed
BasicHandle(std::shared_ptr<HandleExceptionFactory> const& iWhyFailed):
BasicHandle(std::shared_ptr<HandleExceptionFactory> const& iWhyFailed) noexcept(true) :
product_(),
prov_(nullptr),
whyFailedFactory_(iWhyFailed) {}

~BasicHandle() {}
~BasicHandle() = default;

void swap(BasicHandle& other) {
void swap(BasicHandle& other) noexcept(true){
using std::swap;
swap(product_, other.product_);
std::swap(prov_, other.prov_);
swap(whyFailedFactory_,other.whyFailedFactory_);
}

BasicHandle& operator=(BasicHandle const& rhs) {
BasicHandle temp(rhs);
this->swap(temp);
return *this;
}
BasicHandle& operator=(BasicHandle&& rhs) = default;
BasicHandle& operator=(BasicHandle const& rhs) = default;

bool isValid() const {
bool isValid() const noexcept(true) {
return product_ && prov_;
}

bool failedToGet() const {
bool failedToGet() const noexcept(true) {
return bool(whyFailedFactory_);
}

WrapperBase const* wrapper() const {
WrapperBase const* wrapper() const noexcept(true) {
return product_;
}

Provenance const* provenance() const {
Provenance const* provenance() const noexcept(true) {
return prov_;
}

ProductID id() const {
ProductID id() const noexcept(true) {
return prov_->productID();
}

std::shared_ptr<cms::Exception> whyFailed() const {
return whyFailedFactory_->make();
}

std::shared_ptr<HandleExceptionFactory> const& whyFailedFactory() const {
std::shared_ptr<HandleExceptionFactory> const& whyFailedFactory() const noexcept(true) {
return whyFailedFactory_;
}

std::shared_ptr<HandleExceptionFactory>& whyFailedFactory() {
std::shared_ptr<HandleExceptionFactory>& whyFailedFactory() noexcept(true) {
return whyFailedFactory_;
}

void clear() {
void clear() noexcept(true) {
product_ = nullptr;
prov_ = nullptr;
whyFailedFactory_.reset();
}

static BasicHandle makeInvalid() { return BasicHandle(true);}
private:
//This is used to create a special invalid BasicHandle
explicit BasicHandle(bool):product_(nullptr) {}
WrapperBase const* product_;
Provenance const* prov_;
std::shared_ptr<HandleExceptionFactory> whyFailedFactory_;
Expand All @@ -126,7 +121,7 @@ namespace edm {
// Free swap function
inline
void
swap(BasicHandle& a, BasicHandle& b) {
swap(BasicHandle& a, BasicHandle& b) noexcept(true) {
a.swap(b);
}
}
Expand Down
39 changes: 26 additions & 13 deletions DataFormats/Common/interface/ConvertHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,51 @@
#include "DataFormats/Common/interface/BasicHandle.h"
#include "DataFormats/Common/interface/Handle.h"
#include "DataFormats/Common/interface/Wrapper.h"
#include "FWCore/Utilities/interface/Likely.h"

#include <typeinfo>
#include <algorithm>
#include <memory>

namespace edm {

namespace handleimpl {
void throwInvalidReference();
void throwConvertTypeError(std::type_info const& expected, std::type_info const& actual);
std::shared_ptr<edm::HandleExceptionFactory> makeInvalidReferenceException();
}

// Convert from handle-to-void to handle-to-T
template<typename T>
void convert_handle(BasicHandle && bh,
Handle<T>& result) {
if(bh.failedToGet()) {
Handle<T> h(std::move(bh.whyFailedFactory()));
result = std::move(h);
return;
Handle<T> convert_handle(BasicHandle && bh) noexcept(true) {
if UNLIKELY(bh.failedToGet()) {
return Handle<T>(std::move(bh.whyFailedFactory()));
}
void const* basicWrapper = bh.wrapper();
if(basicWrapper == nullptr) {
handleimpl::throwInvalidReference();
if UNLIKELY(nullptr == basicWrapper) {
return Handle<T>{handleimpl::makeInvalidReferenceException()};
}
if(!(bh.wrapper()->dynamicTypeInfo() == typeid(T))) {
auto wrapper = static_cast<Wrapper<T> const*>(basicWrapper);

return Handle<T>(wrapper->product(), bh.provenance());
}

template<typename T>
Handle<T> convert_handle_check_type(BasicHandle && bh) {
if UNLIKELY(bh.failedToGet()) {
return Handle<T>(std::move(bh.whyFailedFactory()));
}
void const* basicWrapper = bh.wrapper();
if UNLIKELY(basicWrapper == nullptr) {
return Handle<T>{handleimpl::makeInvalidReferenceException()};
}
if UNLIKELY(!(bh.wrapper()->dynamicTypeInfo() == typeid(T))) {
handleimpl::throwConvertTypeError(typeid(T), bh.wrapper()->dynamicTypeInfo());
}
Wrapper<T> const* wrapper = static_cast<Wrapper<T> const*>(basicWrapper);

Handle<T> h(wrapper->product(), bh.provenance());
h.swap(result);

return Handle<T>(wrapper->product(), bh.provenance());
}

}

#endif
8 changes: 8 additions & 0 deletions DataFormats/Common/interface/HandleBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ namespace edm {
std::shared_ptr<HandleExceptionFactory> const&
whyFailedFactory() const { return whyFailedFactory_;}

explicit operator bool () const {
return isValid();
}

bool operator!() const {
return not isValid();
}

protected:

void const* productStorage() const;
Expand Down
14 changes: 10 additions & 4 deletions DataFormats/Common/src/ConvertHandle.cc
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
#include "DataFormats/Common/interface/ConvertHandle.h"
#include "FWCore/Utilities/interface/EDMException.h"
#include "DataFormats/Common/interface/FunctorHandleExceptionFactory.h"

namespace edm {
namespace handleimpl {
void throwInvalidReference() {
throw Exception(errors::InvalidReference, "NullPointer")
<< "edm::BasicHandle has null pointer to Wrapper";
}
static std::shared_ptr<HandleExceptionFactory> s_invalidRefFactory = makeHandleExceptionFactory([]()->std::shared_ptr<cms::Exception> {
std::shared_ptr<cms::Exception> whyFailed = std::make_shared<edm::Exception>(errors::InvalidReference, "NullPointer");
*whyFailed << "Handle has null pointer to data product";
return whyFailed;
});

std::shared_ptr<HandleExceptionFactory> makeInvalidReferenceException() {
return s_invalidRefFactory;
}

void throwConvertTypeError(std::type_info const& expected, std::type_info const& actual) {
throw Exception(errors::LogicError, "TypeMismatch")
<< "edm::BasicHandle contains a product of type " << actual.name() << ".\n"
Expand Down
4 changes: 2 additions & 2 deletions FWCore/Common/interface/EventBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ namespace edm {
EventBase::getByLabel(InputTag const& tag, Handle<T>& result) const {
result.clear();
BasicHandle bh = this->getByLabelImpl(typeid(edm::Wrapper<T>), typeid(T), tag);
convert_handle(std::move(bh), result); // throws on conversion error
result = convert_handle<T>(std::move(bh));
if (result.failedToGet()) {
return false;
}
Expand All @@ -106,7 +106,7 @@ namespace edm {
EventBase::get(ProductID const& pid, Handle<T>& result) const {
result.clear();
BasicHandle bh = this->getImpl(typeid(T), pid);
convert_handle(std::move(bh), result); // throws on conversion error
result = convert_handle_check_type<T>(std::move(bh));
if (result.failedToGet()) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion FWCore/Common/interface/LuminosityBlockBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace edm {
LuminosityBlockBase::getByLabel(const InputTag& tag, Handle<T>& result) const {
result.clear();
BasicHandle bh = this->getByLabelImpl(typeid(Wrapper<T>), typeid(T), tag);
convert_handle(std::move(bh), result); // throws on conversion error
result = convert_handle<T>(std::move(bh));
if (result.failedToGet()) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion FWCore/Common/interface/RunBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ namespace edm {
RunBase::getByLabel(InputTag const& tag, Handle<T>& result) const {
result.clear();
BasicHandle bh = this->getByLabelImpl(typeid(Wrapper<T>), typeid(T), tag);
convert_handle(std::move(bh), result); // throws on conversion error
result = convert_handle<T>(std::move(bh));
if (result.failedToGet()) {
return false;
}
Expand Down
Loading

0 comments on commit fc4815a

Please sign in to comment.