Skip to content
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

Provide easier to use ::get and ::getHandle methods for Event, Run and LuminosityBlock #25707

Merged
merged 6 commits into from
Jan 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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