Skip to content
Snippets Groups Projects
Commit bcf55dec authored by Gerhard Raven's avatar Gerhard Raven
Browse files

Add support to DataWriteHandle for writing 'views' into the TES

Allow a second template argument on `DataObjectWriteHandle` eg.
DataObjectWriteHandle<GetType,PutType> (note: by default, in case
of a single template argument, PutType=GetType, and the original
behaviour is kept).  In this case, `DataObjectWriteHandle::put`
will accept an rvalue reference to `PutType`, which it will create
a dedicated 'wrapper', which contains both the moved instance of
`PutType` as well as a `GetType` constructed from the moved instance,
into the event store. This wrapper can be retrieved and unwrapped
by a `DataObjectReadHandle<GetType>`.
parent 05d3399b
No related branches found
No related tags found
1 merge request!1151Add support to DataWriteHandle for writing (partially type erased) 'views' into the TES
Pipeline #2074101 passed
Showing
with 348 additions and 177 deletions
......@@ -144,13 +144,13 @@ namespace Gaudi::Functional::details {
template <typename Out1, typename Out2,
typename = std::enable_if_t<std::is_constructible_v<Out1, Out2> && std::is_base_of_v<DataObject, Out1>>>
Out1* put( const DataObjectHandle<Out1>& out_handle, Out2&& out ) {
auto put( const DataObjectHandle<Out1>& out_handle, Out2&& out ) {
return out_handle.put( std::make_unique<Out1>( std::forward<Out2>( out ) ) );
}
template <typename Out1, typename Out2, typename = std::enable_if_t<std::is_constructible_v<Out1, Out2>>>
void put( const DataObjectHandle<AnyDataWrapper<Out1>>& out_handle, Out2&& out ) {
out_handle.put( std::forward<Out2>( out ) );
auto put( const DataObjectHandle<AnyDataWrapper<Out1>>& out_handle, Out2&& out ) {
return out_handle.put( std::forward<Out2>( out ) );
}
// optional put
......
......@@ -85,6 +85,12 @@ namespace Gaudi::Functional {
using OutputHandle = Handle<T>;
};
template <typename Data, typename View>
struct writeViewFor {
template <typename T>
using OutputHandle = std::enable_if_t<std::is_same_v<T, Data>, DataObjectWriteHandle<View, Data>>;
};
// this uses the defaults -- and it itself is the default ;-)
using useDefaults = use_<>;
......
......@@ -79,13 +79,9 @@ namespace Gaudi {
typename _GetType<TYPE>::return_type getFromTS( IDataProviderSvc* service, std::string_view location ) {
DataObject* obj = nullptr;
// Return the casted pointer if the retrieve was successful or nullptr otherwise.
StatusCode sc = service->retrieveObject( location, obj );
if ( sc.isSuccess() ) {
typename _GetType<TYPE>::return_type tobj = dynamic_cast<typename _GetType<TYPE>::return_type>( obj );
return tobj;
} else {
return nullptr;
}
return service->retrieveObject( location, obj ).isSuccess()
? dynamic_cast<typename _GetType<TYPE>::return_type>( obj )
: nullptr;
}
// ========================================================================
/** Helper function to provide the minimal lookup and cast functionality
......@@ -98,17 +94,13 @@ namespace Gaudi {
DataObject* obj = nullptr;
// Return the casted pointer if the retrieve was successful or nullptr otherwise.
StatusCode sc = service->retrieveObject( location, obj );
if ( sc.isSuccess() ) {
typename _GetType<TYPE>::return_type tobj = dynamic_cast<typename _GetType<TYPE>::return_type>( obj );
if ( !tobj ) {
// try with AnyDataWrapper
AnyDataWrapper<TYPE>* tobj2 = dynamic_cast<AnyDataWrapper<TYPE>*>( obj );
if ( tobj2 ) { tobj = &( tobj2->getData() ); }
}
return tobj;
} else {
return nullptr;
if ( sc.isFailure() ) return nullptr;
auto tobj = dynamic_cast<typename _GetType<TYPE>::return_type>( obj );
if ( !tobj ) {
// try with AnyDataWrapper
if ( auto tobj2 = dynamic_cast<AnyDataWrapper<TYPE>*>( obj ); tobj2 ) { tobj = &( tobj2->getData() ); }
}
return tobj;
}
// ========================================================================
/** @struct GetData GaudiUtils/GetData.h
......
......@@ -40,8 +40,8 @@ gaudi_add_module(GaudiExamples
src/AlgTools/TestToolAlg.cpp
src/AlgTools/TestToolAlgFailure.cpp
src/AlgTools/TestToolFailing.cpp
src/AnyData/AnyDataGetAlgorithm.cpp
src/AnyData/AnyDataPutAlgorithm.cpp
src/AnyData/AnyDataAlgorithm.cpp
src/AnyData/AnyViewAlgorithm.cpp
src/Auditors/AuditorTestAlg.cpp
src/Auditors/LoggingAuditor.cpp
src/bug_34121/bug34121_MyAlgorithm.cpp
......
......@@ -8,48 +8,85 @@
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\***********************************************************************************/
// Include files
#include <vector>
// from Gaudi
#include "GaudiAlg/GaudiAlgorithm.h"
#include "GaudiKernel/AnyDataWrapper.h"
// local
#include "AnyDataGetAlgorithm.h"
#include "GaudiKernel/DataObjectHandle.h"
#include <string>
#include <vector>
//-----------------------------------------------------------------------------
// Implementation file for class : AnyDataGetAlgorithm
// Implementation file for class : AnyData{Get,Put}Algorithm
//
// 2016-05-26 : Roel Aaij
//-----------------------------------------------------------------------------
/** @class AnyDataPutAlgorithm AnyDataPutAlgorithm.h AnyData/AnyDataPutAlgorithm.h
*
*
* @author Roel Aaij
* @date 2016-05-26
*/
class AnyDataPutAlgorithm : public GaudiAlgorithm {
Gaudi::Property<std::string> m_loc{this, "Location", "Test"};
DataObjectWriteHandle<std::vector<int>> m_ids{this, "Output", "/Event/Test/Ids"};
std::vector<DataObjectWriteHandle<int>> m_id_vec;
// Declaration of the Algorithm Factory
DECLARE_COMPONENT_WITH_ID( AnyDataGetAlgorithm<int>, "AnyDataGetAlgorithm_Int" )
DECLARE_COMPONENT_WITH_ID( AnyDataGetAlgorithm<std::vector<int>>, "AnyDataGetAlgorithm_VectorInt" )
public:
AnyDataPutAlgorithm( const std::string& name, ISvcLocator* pSvcLocator ) : GaudiAlgorithm( name, pSvcLocator ) {
for ( int i = 0; i < 100; i++ ) { m_id_vec.emplace_back( "/Event/Test/Ids" + std::to_string( i ), this ); }
}
StatusCode execute() override {
if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Execute" << endmsg;
auto i = std::make_unique<AnyDataWrapper<int>>( 0 );
auto j = std::make_unique<AnyDataWrapper<std::vector<int>>>( std::vector<int>{0, 1, 2, 3} );
namespace {
using std::vector;
}
put( std::move( i ), m_loc + "/One" );
put( std::move( j ), m_loc + "/Two" );
//=============================================================================
// Main execution
//=============================================================================
m_ids.put( std::vector<int>( {42, 84} ) );
for ( int i = 0; i < 100; ++i ) m_id_vec[i].put( std::move( i ) );
return StatusCode::SUCCESS;
}
};
// Declaration of the Algorithm Factory
DECLARE_COMPONENT( AnyDataPutAlgorithm )
/** @class AnyDataGetAlgorithm AnyDataGetAlgorithm.h AnyData/AnyDataGetAlgorithm.h
*
*
* @author Roel Aaij
* @date 2016-05-26
*/
template <class T>
StatusCode AnyDataGetAlgorithm<T>::execute() {
class AnyDataGetAlgorithm : public GaudiAlgorithm {
Gaudi::Property<std::string> m_location{this, "Location"};
DataObjectReadHandle<std::vector<int>> m_ids{this, "Input", "/Event/Test/Ids"};
if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Execute" << endmsg;
public:
using GaudiAlgorithm::GaudiAlgorithm;
auto base = getIfExists<AnyDataWrapperBase>( m_location );
if ( base ) { info() << "Got base from " << m_location.value() << endmsg; }
const auto i = dynamic_cast<const AnyDataWrapper<T>*>( base );
if ( i ) {
info() << "Got " << System::typeinfoName( typeid( T ) ) << " from " << m_location.value() << ": " << i->getData()
<< endmsg;
StatusCode execute() override {
if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Execute" << endmsg;
auto base = getIfExists<AnyDataWrapperBase>( m_location );
if ( base ) { info() << "Got base from " << m_location.value() << endmsg; }
const auto i = dynamic_cast<const AnyDataWrapper<T>*>( base );
if ( i ) {
info() << "Got " << System::typeinfoName( typeid( T ) ) << " from " << m_location.value() << ": " << i->getData()
<< endmsg;
}
const auto& ids = m_ids.get();
info() << "AnyDataHandler holds:";
for ( const auto& i : *ids ) info() << i << " ";
info() << endmsg;
return StatusCode::SUCCESS;
}
};
const auto& ids = m_ids.get();
info() << "AnyDataHandler holds:";
for ( const auto& i : *ids ) info() << i << " ";
info() << endmsg;
return StatusCode::SUCCESS;
}
// Declaration of the Algorithm Factory
DECLARE_COMPONENT_WITH_ID( AnyDataGetAlgorithm<int>, "AnyDataGetAlgorithm_Int" )
DECLARE_COMPONENT_WITH_ID( AnyDataGetAlgorithm<std::vector<int>>, "AnyDataGetAlgorithm_VectorInt" )
/***********************************************************************************\
* (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
* *
* This software is distributed under the terms of the Apache version 2 licence, *
* copied verbatim in the file "LICENSE". *
* *
* In applying this licence, CERN does not waive the privileges and immunities *
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\***********************************************************************************/
// Include files
#include <string>
#include <vector>
// from Gaudi
#include "GaudiKernel/AnyDataWrapper.h"
// local
#include "AnyDataPutAlgorithm.h"
//-----------------------------------------------------------------------------
// Implementation file for class : AnyDataPutAlgorithm
//
// 2016-05-26 : Roel Aaij
//-----------------------------------------------------------------------------
// Declaration of the Algorithm Factory
DECLARE_COMPONENT( AnyDataPutAlgorithm )
//=============================================================================
// Standard constructor, initializes variables
//=============================================================================
AnyDataPutAlgorithm::AnyDataPutAlgorithm( const std::string& name, ISvcLocator* pSvcLocator )
: GaudiAlgorithm( name, pSvcLocator ) {
for ( int i = 0; i < 100; i++ ) { m_id_vec.emplace_back( "/Event/Test/Ids" + std::to_string( i ), this ); }
}
//=============================================================================
// Main execution
//=============================================================================
StatusCode AnyDataPutAlgorithm::execute() {
if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Execute" << endmsg;
auto i = std::make_unique<AnyDataWrapper<int>>( 0 );
auto j = std::make_unique<AnyDataWrapper<std::vector<int>>>( std::vector<int>{0, 1, 2, 3} );
put( std::move( i ), m_loc + "/One" );
put( std::move( j ), m_loc + "/Two" );
m_ids.put( std::vector<int>( {42, 84} ) );
for ( int i = 0; i < 100; ++i ) m_id_vec[i].put( std::move( i ) );
return StatusCode::SUCCESS;
}
/***********************************************************************************\
* (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
* *
* This software is distributed under the terms of the Apache version 2 licence, *
* copied verbatim in the file "LICENSE". *
* *
* In applying this licence, CERN does not waive the privileges and immunities *
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\***********************************************************************************/
#ifndef ANYDATA_ANADATAPUTALGORITHM_H
#define ANYDATA_ANADATAPUTALGORITHM_H 1
// Include files
#include <string>
#include <vector>
// from Gaudi
#include "GaudiAlg/GaudiAlgorithm.h"
#include "GaudiKernel/AnyDataHandle.h"
/** @class AnyDataPutAlgorithm AnyDataPutAlgorithm.h AnyData/AnyDataPutAlgorithm.h
*
*
* @author Roel Aaij
* @date 2016-05-26
*/
class AnyDataPutAlgorithm : public GaudiAlgorithm {
public:
/// Standard constructor
AnyDataPutAlgorithm( const std::string& name, ISvcLocator* pSvcLocator );
StatusCode execute() override; ///< Algorithm execution
private:
Gaudi::Property<std::string> m_loc{this, "Location", "Test"};
DataObjectWriteHandle<std::vector<int>> m_ids{this, "Output", "/Event/Test/Ids"};
std::vector<DataObjectWriteHandle<int>> m_id_vec;
};
#endif // ANYDATA_ANADATAPUTALGORITHM_H
......@@ -8,33 +8,58 @@
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\***********************************************************************************/
#ifndef ANYDATA_ANADATAGETALGORITHM_H
#define ANYDATA_ANADATAGETALGORITHM_H 1
// Include files
#include "GaudiAlg/Consumer.h"
#include "GaudiAlg/Producer.h"
#include "GaudiKernel/Algorithm.h"
#include "GaudiKernel/DataObjectHandle.h"
#include <gsl/span>
#include <string>
#include <string_view>
#include <vector>
// from Gaudi
#include "GaudiAlg/GaudiAlgorithm.h"
#include "GaudiKernel/DataObjectHandle.h"
/** @class AnyDataGetAlgorithm AnyDataGetAlgorithm.h AnyData/AnyDataGetAlgorithm.h
*
*
* @author Roel Aaij
* @date 2016-05-26
*/
template <class T>
class AnyDataGetAlgorithm : public GaudiAlgorithm {
public:
/// Standard constructor
AnyDataGetAlgorithm( const std::string& name, ISvcLocator* svcLoc ) : GaudiAlgorithm( name, svcLoc ) {}
StatusCode execute() override; ///< Algorithm execution
private:
Gaudi::Property<std::string> m_location{this, "Location"};
DataObjectReadHandle<std::vector<int>> m_ids{this, "Input", "/Event/Test/Ids"};
using BaseClass_t = Gaudi::Functional::Traits::BaseClass_t<Gaudi::Algorithm>;
template <typename Data, typename View>
using writeViewFor = Gaudi::Functional::Traits::use_<Gaudi::Functional::Traits::writeViewFor<Data, View>, BaseClass_t>;
struct ProduceStringView : Gaudi::Functional::Producer<std::string(), writeViewFor<std::string, std::string_view>> {
ProduceStringView( const std::string& name, ISvcLocator* svcLoc )
: Producer{name, svcLoc, {"Output", "/Event/Test/StringView"}} {}
std::string operator()() const override { return "Hello World"; }
};
DECLARE_COMPONENT( ProduceStringView )
struct ProduceIntView
: Gaudi::Functional::Producer<std::vector<int>(), writeViewFor<std::vector<int>, gsl::span<const int>>> {
ProduceIntView( const std::string& name, ISvcLocator* svcLoc )
: Producer{name, svcLoc, {"Output", "/Event/Test/IntView"}} {}
std::vector<int> operator()() const override {
std::vector<int> vi{1, 2, 3, 5, 8, 13, 21, 34};
info() << "made vector with data at : " << vi.data() << endmsg;
return vi;
}
};
DECLARE_COMPONENT( ProduceIntView )
struct GetStringView : Gaudi::Functional::Consumer<void( std::string_view const& ), BaseClass_t> {
GetStringView( const std::string& name, ISvcLocator* svcLoc )
: Consumer{name, svcLoc, {"Input", "/Event/Test/StringView"}} {}
void operator()( const std::string_view& sv ) const override { info() << sv << endmsg; }
};
DECLARE_COMPONENT( GetStringView )
struct GetIntView : Gaudi::Functional::Consumer<void( gsl::span<const int> const& ), BaseClass_t> {
GetIntView( const std::string& name, ISvcLocator* svcLoc )
: Consumer{name, svcLoc, {"Input", "/Event/Test/IntView"}} {}
void operator()( const gsl::span<const int>& view ) const override {
info() << "got a span with data at : " << view.data() << endmsg;
auto& out = info();
for ( int i : view ) out << i << " ";
out << endmsg;
}
};
#endif // ANYDATA_ANADATAGETALGORITHM_H
DECLARE_COMPONENT( GetIntView )
<?xml version="1.0" ?><!DOCTYPE extension PUBLIC '-//QM/2.3/Extension//EN' 'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
<!--
(c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations
This software is distributed under the terms of the Apache version 2 licence,
copied verbatim in the file "LICENSE".
In applying this licence, CERN does not waive the privileges and immunities
granted to it by virtue of its status as an Intergovernmental Organization
or submit itself to any jurisdiction.
-->
<extension class="GaudiTest.GaudiExeTest" kind="test">
<argument name="program"><text>gaudirun.py</text></argument>
<argument name="options"><text>
from Gaudi.Configuration import *
from Configurables import ProduceStringView, ProduceIntView, GetStringView, GetIntView
from Configurables import EvtDataSvc
EvtDataSvc("EventDataSvc").RootCLID = 1
EvtDataSvc("EventDataSvc").RootName = "/Event"
EvtDataSvc("EventDataSvc").ForceLeaves = True
app = ApplicationMgr(TopAlg = [ ProduceStringView(), ProduceIntView(), GetStringView(), GetIntView() ],
EvtSel = "NONE",
EvtMax = 2)
</text></argument>
<argument name="reference"><text>refs/anyview.ref</text></argument>
<argument name="exit_code"><integer>0</integer></argument>
</extension>
# setting LC_ALL to "C"
# --> Including file '/tmp/tmpz_UACG.py'
# <-- End of file '/tmp/tmpz_UACG.py'
ApplicationMgr SUCCESS
====================================================================================================================================
Welcome to ApplicationMgr (GaudiCoreSvc v34r1)
running on stbc-i1.nikhef.nl on Sat Nov 7 15:16:48 2020
====================================================================================================================================
ApplicationMgr INFO Application Manager Configured successfully
EventLoopMgr WARNING Unable to locate service "EventSelector"
EventLoopMgr WARNING No events will be processed from external input.
ApplicationMgr INFO Application Manager Initialized successfully
ApplicationMgr INFO Application Manager Started successfully
ProduceIntView INFO made vector with data at : 0x1f6baf0
GetStringView INFO Hello World
GetIntView INFO got a span with data at : 0x1f6baf0
GetIntView INFO 1 2 3 5 8 13 21 34
ProduceIntView INFO made vector with data at : 0x1f6baf0
GetStringView INFO Hello World
GetIntView INFO got a span with data at : 0x1f6baf0
GetIntView INFO 1 2 3 5 8 13 21 34
ApplicationMgr INFO Application Manager Stopped successfully
EventLoopMgr INFO Histograms converted successfully according to request.
ApplicationMgr INFO Application Manager Finalized successfully
ApplicationMgr INFO Application Manager Terminated successfully
......@@ -8,14 +8,12 @@
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\***********************************************************************************/
#ifndef GAUDIKERNEL_ANYDATAWRAPPER_H
#define GAUDIKERNEL_ANYDATAWRAPPER_H
// Include files
#pragma once
#include "GaudiKernel/DataObject.h"
#include <cstddef>
#include <iterator>
#include <optional>
#include <utility>
namespace details {
using std::size;
......@@ -32,24 +30,37 @@ struct GAUDI_API AnyDataWrapperBase : DataObject {
virtual std::optional<std::size_t> size() const = 0;
};
template <class T>
class GAUDI_API AnyDataWrapper final : public AnyDataWrapperBase {
public:
AnyDataWrapper( T&& data ) : m_data( std::move( data ) ){};
template <typename T>
class GAUDI_API AnyDataWrapper : public AnyDataWrapperBase {
protected:
T m_data;
AnyDataWrapper( AnyDataWrapper&& other )
: AnyDataWrapperBase( std::move( other ) ), m_data( std::move( other.m_data ) ){};
public:
AnyDataWrapper( T&& data ) : m_data{std::move( data )} {};
AnyDataWrapper( AnyDataWrapper&& ) = delete;
AnyDataWrapper( AnyDataWrapper const& ) = delete;
AnyDataWrapper& operator=( AnyDataWrapper&& ) = delete;
AnyDataWrapper& operator=( AnyDataWrapper const& ) = delete;
const T& getData() const { return m_data; }
T& getData() { return m_data; }
std::optional<std::size_t> size() const override {
using details::size;
return size( m_data );
return size( getData() );
}
private:
T m_data;
};
#endif
template <typename ViewType, typename OwnedType>
class GAUDI_API AnyDataWithViewWrapper : public AnyDataWrapper<ViewType> {
OwnedType m_owned;
public:
AnyDataWithViewWrapper( OwnedType&& data ) : AnyDataWrapper<ViewType>{{}}, m_owned{std::move( data )} {
AnyDataWrapper<ViewType>::m_data = ViewType{std::as_const( m_owned )};
}
AnyDataWithViewWrapper( AnyDataWithViewWrapper&& ) = delete;
AnyDataWithViewWrapper( AnyDataWithViewWrapper const& ) = delete;
AnyDataWithViewWrapper& operator=( AnyDataWithViewWrapper&& ) = delete;
AnyDataWithViewWrapper& operator=( AnyDataWithViewWrapper const& ) = delete;
};
......@@ -69,21 +69,24 @@ namespace details {
return ok;
}
template <typename T>
template <typename T, typename U>
struct Payload_helper {
using type = std::conditional_t<std::is_base_of_v<DataObject, T>, T, AnyDataWrapper<std::remove_const_t<T>>>;
using type =
std::conditional_t<std::is_base_of_v<DataObject, T> && std::is_same_v<T, U>, T,
std::conditional_t<std::is_same_v<T, U>, AnyDataWrapper<std::remove_const_t<T>>,
AnyDataWithViewWrapper<std::remove_const_t<T>, std::remove_const_t<U>>>>;
};
template <typename T>
struct Payload_helper<Gaudi::Range_<T>> {
template <typename T, typename U>
struct Payload_helper<Gaudi::Range_<T>, U> {
using type = Gaudi::Range_<T>;
};
template <typename T>
struct Payload_helper<Gaudi::NamedRange_<T>> {
template <typename T, typename U>
struct Payload_helper<Gaudi::NamedRange_<T>, U> {
using type = Gaudi::NamedRange_<T>;
};
template <typename T>
using Payload_t = typename Payload_helper<T>::type;
template <typename T, typename U = T>
using Payload_t = typename Payload_helper<T, U>::type;
} // namespace details
//---------------------------------------------------------------------------
......@@ -173,10 +176,8 @@ T* DataObjectHandle<T>::get( bool mustExist ) const {
template <typename T>
T* DataObjectHandle<T>::put( std::unique_ptr<T> objectp ) const {
assert( m_init );
StatusCode rc = m_EDS->registerObject( objKey(), objectp.get() );
if ( !rc.isSuccess() ) {
throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<T>::put", StatusCode::FAILURE );
}
StatusCode sc = m_EDS->registerObject( objKey(), objectp.get() );
if ( !sc.isSuccess() ) { throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<T>::put", sc ); }
return objectp.release();
}
......@@ -296,7 +297,14 @@ public:
/**
* Register object in transient store
*/
const T* put( T&& object ) const;
const T* put( T&& obj ) const {
assert( m_init );
auto objectp = std::make_unique<AnyDataWrapper<T>>( std::move( obj ) );
if ( auto sc = m_EDS->registerObject( objKey(), objectp.get() ); sc.isFailure() ) {
throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<AnyDataWrapper<T>>::put", sc );
}
return &objectp.release()->getData();
}
/**
* Size of boxed item, if boxed item has a 'size' method
......@@ -310,40 +318,81 @@ public:
}
private:
AnyDataWrapper<T>* _get( bool mustExist ) const;
mutable bool m_goodType = false;
AnyDataWrapper<T>* _get( bool mustExist ) const {
auto obj = fetch();
if ( UNLIKELY( !obj ) ) {
if ( mustExist ) {
throw GaudiException( "Cannot retrieve " + objKey() + " from transient store.",
m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
} else {
return nullptr;
}
}
if ( UNLIKELY( !m_goodType ) ) m_goodType = ::details::verifyType<AnyDataWrapper<T>>( obj );
return static_cast<AnyDataWrapper<T>*>( obj );
}
mutable bool m_goodType = false;
};
//---------------------------------------------------------------------------
/// specialization for AnyDataWithViewWrapper
template <typename View, typename Owned>
class DataObjectHandle<AnyDataWithViewWrapper<View, Owned>> : public DataObjectHandleBase {
public:
using DataObjectHandleBase::DataObjectHandleBase;
template <typename T>
AnyDataWrapper<T>* DataObjectHandle<AnyDataWrapper<T>>::_get( bool mustExist ) const {
auto obj = fetch();
if ( UNLIKELY( !obj ) ) {
if ( mustExist ) {
throw GaudiException( "Cannot retrieve " + objKey() + " from transient store.",
m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
/**
* Retrieve object from transient data store
*/
View* get() const { return &_get( true )->getData(); }
View* getIfExists() const {
auto data = _get( false );
return data ? &data->getData() : nullptr;
}
} else {
return nullptr;
/**
* Register object in transient store
*/
const View* put( std::unique_ptr<AnyDataWithViewWrapper<View, Owned>> objectp ) const {
assert( m_init );
if ( auto sc = m_EDS->registerObject( objKey(), objectp.get() ); sc.isFailure() ) {
throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<AnyDataWithViewWrapper<T>::put", sc );
}
return &objectp.release()->getData();
}
const View* put( Owned&& obj ) const {
return put( std::make_unique<AnyDataWithViewWrapper<View, Owned>>( std::move( obj ) ) );
}
if ( UNLIKELY( !m_goodType ) ) m_goodType = ::details::verifyType<AnyDataWrapper<T>>( obj );
return static_cast<AnyDataWrapper<T>*>( obj );
}
//---------------------------------------------------------------------------
/**
* Size of boxed item, if boxed item has a 'size' method
*/
std::optional<std::size_t> size() const { return _get()->size(); }
template <typename T>
const T* DataObjectHandle<AnyDataWrapper<T>>::put( T&& obj ) const {
assert( m_init );
auto objectp = std::make_unique<AnyDataWrapper<T>>( std::move( obj ) );
StatusCode rc = m_EDS->registerObject( objKey(), objectp.get() );
if ( rc.isFailure() ) {
throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<T>::put", StatusCode::FAILURE );
std::string pythonRepr() const override {
auto repr = DataObjectHandleBase::pythonRepr();
boost::replace_all( repr, default_type, System::typeinfoName( typeid( View ) ) );
return repr;
}
return &objectp.release()->getData();
}
private:
AnyDataWithViewWrapper<View, Owned>* _get( bool mustExist ) const {
auto obj = fetch();
if ( UNLIKELY( !obj ) ) {
if ( mustExist ) {
throw GaudiException( "Cannot retrieve " + objKey() + " from transient store.",
m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
} else {
return nullptr;
}
}
if ( UNLIKELY( !m_goodType ) ) m_goodType = ::details::verifyType<AnyDataWithViewWrapper<View, Owned>>( obj );
return static_cast<AnyDataWithViewWrapper<View, Owned>*>( obj );
}
mutable bool m_goodType = false;
};
//---------------------------- user-facing interface ----------
......@@ -369,22 +418,22 @@ public:
: DataObjectReadHandle( args, std::index_sequence_for<Args...>{} ) {}
};
template <typename T>
class DataObjectWriteHandle : public DataObjectHandle<::details::Payload_t<T>> {
template <typename T, typename U = T>
class DataObjectWriteHandle : public DataObjectHandle<::details::Payload_t<T, U>> {
template <typename... Args, std::size_t... Is>
DataObjectWriteHandle( const std::tuple<Args...>& args, std::index_sequence<Is...> )
: DataObjectWriteHandle( std::get<Is>( args )... ) {}
public:
DataObjectWriteHandle( const DataObjID& k, IDataHandleHolder* owner )
: DataObjectHandle<::details::Payload_t<T>>{k, Gaudi::DataHandle::Writer, owner} {}
: DataObjectHandle<::details::Payload_t<T, U>>{k, Gaudi::DataHandle::Writer, owner} {}
/// Autodeclaring constructor with property name, mode, key and documentation.
/// @note the use std::enable_if is required to avoid ambiguities
template <typename OWNER, typename K, typename = std::enable_if_t<std::is_base_of_v<IProperty, OWNER>>>
DataObjectWriteHandle( OWNER* owner, std::string propertyName, const K& key = {}, std::string doc = "" )
: DataObjectHandle<::details::Payload_t<T>>( owner, Gaudi::DataHandle::Writer, std::move( propertyName ), key,
std::move( doc ) ) {}
: DataObjectHandle<::details::Payload_t<T, U>>( owner, Gaudi::DataHandle::Writer, std::move( propertyName ), key,
std::move( doc ) ) {}
template <typename... Args>
DataObjectWriteHandle( const std::tuple<Args...>& args )
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment