The Gaudi Framework  v33r0 (d5ea422b)
DataObjectHandle.h
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #ifndef GAUDIHIVE_DATAOBJECTHANDLE_H
12 #define GAUDIHIVE_DATAOBJECTHANDLE_H
13 
18 #include "GaudiKernel/IProperty.h"
19 #include "GaudiKernel/IRegistry.h"
20 #include "GaudiKernel/NamedRange.h"
21 
22 #include "boost/algorithm/string.hpp"
23 #include <type_traits>
24 
25 //---------------------------------------------------------------------------
26 //
27 namespace details {
28  template <typename T>
29  using Converter_t = T ( * )( const DataObject* );
30 
31  template <typename Range, typename StorageType>
32  Range make_range( const DataObject* obj ) {
33  auto c = static_cast<const StorageType*>( obj );
34  if ( UNLIKELY( !c ) ) return Range();
35  using std::begin;
36  using std::end;
37  auto first = begin( *c );
38  auto last = end( *c );
39  // return Range( first, last );
40  auto _first = reinterpret_cast<typename Range::const_iterator*>( &first );
41  auto _last = reinterpret_cast<typename Range::const_iterator*>( &last );
42  return Range( *_first, *_last );
43  }
44 
45  template <typename ValueType, typename Range = Gaudi::Range_<typename ValueType::ConstVector>>
47  using Selection = typename ValueType::Selection;
48  auto sel = dynamic_cast<const Selection*>( obj );
49  if ( sel ) return &make_range<Range, typename ValueType::Selection>;
50  auto con = dynamic_cast<std::add_const_t<typename ValueType::Container>*>( obj );
51  if ( con ) return &make_range<Range, typename ValueType::Container>;
52  return nullptr;
53  }
54 
55  template <typename T>
56  bool verifyType( const DataObject* dataObj ) {
57  using Type = std::add_const_t<T>;
58  assert( dataObj != nullptr );
59  auto obj = dynamic_cast<Type*>( dataObj );
60  bool ok = ( obj != nullptr );
61  if ( !ok ) {
62  const auto* registry = dataObj->registry();
63  throw GaudiException( "The type expected for " + registry->identifier() + " is " +
64  System::typeinfoName( typeid( Type ) ) +
65  " and is different from the one of the object in the store which is " +
66  System::typeinfoName( typeid( *dataObj ) ) + ".",
67  "Wrong DataObjectType", StatusCode::FAILURE );
68  }
69  assert( obj == static_cast<Type*>( dataObj ) );
70  return ok;
71  }
72 
73  template <typename T>
74  struct Payload_helper {
75  using type = std::conditional_t<std::is_base_of_v<DataObject, T>, T, AnyDataWrapper<T>>;
76  };
77  template <typename T>
78  struct Payload_helper<Gaudi::Range_<T>> {
80  };
81 
82  template <typename T>
84 } // namespace details
85 
86 //---------------------------------------------------------------------------
87 
98 //---------------------------------------------------------------------------
99 
100 template <typename T>
101 class DataObjectHandle : public DataObjectHandleBase {
102 public:
104 
108  T* get() const { return get( true ); }
109 
114  T* getIfExists() const { return get( false ); }
115 
119  bool exist() const { return get( false ) != nullptr; }
120 
124  T* getOrCreate() const;
125 
129  T* put( std::unique_ptr<T> object ) const;
130 
131  // [[deprecated("please pass a std::unique_ptr instead of a raw pointer")]]
132  T* put( T* object ) const { return put( std::unique_ptr<T>( object ) ); }
133 
134  std::string pythonRepr() const override {
135  auto repr = DataObjectHandleBase::pythonRepr();
136  boost::replace_all( repr, default_type, System::typeinfoName( typeid( T ) ) );
137  return repr;
138  }
139 
140 private:
141  T* get( bool mustExist ) const;
142  mutable bool m_goodType = false;
143 };
144 
145 //---------------------------------------------------------------------------
146 //
154 template <typename T>
155 T* DataObjectHandle<T>::get( bool mustExist ) const {
156  auto dataObj = fetch();
157  if ( UNLIKELY( !dataObj ) ) {
158  if ( mustExist ) { // Problems in getting from the store
159  throw GaudiException( "Cannot retrieve " + objKey() + " from transient store.",
160  m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
161  }
162  return nullptr;
163  }
164  if ( UNLIKELY( !m_goodType ) ) m_goodType = ::details::verifyType<T>( dataObj );
165  return static_cast<T*>( dataObj );
166 }
167 
168 //---------------------------------------------------------------------------
169 template <typename T>
171  assert( m_init );
172  StatusCode rc = m_EDS->registerObject( objKey(), objectp.get() );
173  if ( !rc.isSuccess() ) {
174  throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<T>::put", StatusCode::FAILURE );
175  }
176  return objectp.release();
177 }
178 
179 //---------------------------------------------------------------------------
180 template <typename T>
182  T* obj = get( false );
183  return obj ? obj : put( std::make_unique<T>() );
184 }
185 
186 //---------------------------------------------------------------------------
188 
189 template <typename T>
190 class DataObjectHandle<Gaudi::Range_<T>> : public DataObjectHandleBase {
191 public:
192  using ValueType = std::remove_cv_t<std::remove_pointer_t<typename T::value_type>>;
194 
196 
200  Range get() const;
201 
202  std::string pythonRepr() const override {
203  auto repr = DataObjectHandleBase::pythonRepr();
204  boost::replace_all( repr, default_type, System::typeinfoName( typeid( Gaudi::Range_<T> ) ) );
205  return repr;
206  }
207 
208 private:
209  mutable ::details::Converter_t<Range> m_converter = nullptr;
210 };
211 
212 template <typename ValueType>
213 auto DataObjectHandle<Gaudi::Range_<ValueType>>::get() const -> Range {
214  auto dataObj = fetch();
215  if ( UNLIKELY( !dataObj ) ) {
216  throw GaudiException( "Cannot retrieve " + objKey() + " from transient store.",
217  m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
218  }
219  if ( UNLIKELY( !m_converter ) ) {
220  m_converter = ::details::select_range_converter<ValueType>( dataObj );
221  if ( !m_converter ) {
222  throw GaudiException( "The type requested for " + objKey() + " (" + System::typeinfoName( typeid( ValueType ) ) +
223  ")" + " cannot be obtained from object in event store" + " (" +
224  System::typeinfoName( typeid( *dataObj ) ) + ").",
225  "Wrong DataObjectType", StatusCode::FAILURE );
226  }
227  }
228  return ( *m_converter )( dataObj );
229 }
230 
231 //---------------------------------------------------------------------------
233 template <typename T>
235 public:
237 
241  T* get() const { return &_get( true )->getData(); }
242  T* getIfExists() const {
243  auto data = _get( false );
244  if ( data ) {
245  return &data->getData();
246  } else {
247  return nullptr;
248  }
249  }
250 
254  const T* put( T&& object ) const;
255 
259  std::optional<std::size_t> size() const { return _get()->size(); }
260 
261  std::string pythonRepr() const override {
262  auto repr = DataObjectHandleBase::pythonRepr();
263  boost::replace_all( repr, default_type, System::typeinfoName( typeid( T ) ) );
264  return repr;
265  }
266 
267 private:
268  AnyDataWrapper<T>* _get( bool mustExist ) const;
269  mutable bool m_goodType = false;
270 };
271 
272 //---------------------------------------------------------------------------
273 
274 template <typename T>
276  auto obj = fetch();
277  if ( UNLIKELY( !obj ) ) {
278  if ( mustExist ) {
279  throw GaudiException( "Cannot retrieve " + objKey() + " from transient store.",
280  m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
281 
282  } else {
283  return nullptr;
284  }
285  }
286  if ( UNLIKELY( !m_goodType ) ) m_goodType = ::details::verifyType<AnyDataWrapper<T>>( obj );
287  return static_cast<AnyDataWrapper<T>*>( obj );
288 }
289 
290 //---------------------------------------------------------------------------
291 
292 template <typename T>
293 const T* DataObjectHandle<AnyDataWrapper<T>>::put( T&& obj ) const {
294  assert( m_init );
295  auto objectp = std::make_unique<AnyDataWrapper<T>>( std::move( obj ) );
296  StatusCode rc = m_EDS->registerObject( objKey(), objectp.get() );
297  if ( rc.isFailure() ) {
298  throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<T>::put", StatusCode::FAILURE );
299  }
300  return &objectp.release()->getData();
301 }
302 
303 //---------------------------- user-facing interface ----------
304 
305 template <typename T>
306 class DataObjectReadHandle : public DataObjectHandle<::details::Payload_t<T>> {
307  template <typename... Args, std::size_t... Is>
308  DataObjectReadHandle( const std::tuple<Args...>& args, std::index_sequence<Is...> )
309  : DataObjectReadHandle( std::get<Is>( args )... ) {}
310 
311 public:
314 
317  template <typename OWNER, typename K, typename = std::enable_if_t<std::is_base_of_v<IProperty, OWNER>>>
318  DataObjectReadHandle( OWNER* owner, std::string propertyName, const K& key = {}, std::string doc = "" )
320  std::move( doc ) ) {}
321 
322  template <typename... Args>
324  : DataObjectReadHandle( args, std::index_sequence_for<Args...>{} ) {}
325 };
326 
327 template <typename T>
328 class DataObjectWriteHandle : public DataObjectHandle<::details::Payload_t<T>> {
329  template <typename... Args, std::size_t... Is>
330  DataObjectWriteHandle( const std::tuple<Args...>& args, std::index_sequence<Is...> )
331  : DataObjectWriteHandle( std::get<Is>( args )... ) {}
332 
333 public:
336 
339  template <typename OWNER, typename K, typename = std::enable_if_t<std::is_base_of_v<IProperty, OWNER>>>
340  DataObjectWriteHandle( OWNER* owner, std::string propertyName, const K& key = {}, std::string doc = "" )
342  std::move( doc ) ) {}
343 
344  template <typename... Args>
346  : DataObjectWriteHandle( args, std::index_sequence_for<Args...>{} ) {}
347 };
348 
349 #endif
DataObjectWriteHandle(OWNER *owner, std::string propertyName, const K &key={}, std::string doc="")
Autodeclaring constructor with property name, mode, key and documentation.
#define UNLIKELY(x)
Definition: Kernel.h:106
Out1 * put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
bool exist() const
Check the existence of the object in the transient store.
Define general base for Gaudi exception.
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:82
Gaudi::Range_< typename ValueType::ConstVector > Range
T * get() const
Retrieve object from transient data store.
static const std::string default_type
DataObjectReadHandle(const DataObjID &k, IDataHandleHolder *owner)
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:308
auto end(reverse_wrapper< T > &w)
Definition: reverse.h:52
virtual IDataHandleHolder * owner() const
Definition: DataHandle.h:50
DataObjectReadHandle(OWNER *owner, std::string propertyName, const K &key={}, std::string doc="")
Autodeclaring constructor with property name, mode, key and documentation.
std::string pythonRepr() const override
T * put(std::unique_ptr< T > object) const
Register object in transient store.
STL namespace.
T end(T... args)
bool verifyType(const DataObject *dataObj)
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
T * getIfExists() const
Bypass check of existence of object in transient store Only uses main location of the.
T release(T... args)
std::string pythonRepr() const override
STL class.
std::string pythonRepr() const override
DataObjectHandle.h GaudiKernel/DataObjectHandle.h.
Definition: AlgTool.h:36
T * put(T *object) const
std::optional< std::size_t > size() const
Size of boxed item, if boxed item has a 'size' method.
Range make_range(const DataObject *obj)
typename Payload_helper< T >::type Payload_t
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:61
This file has been imported from LoKi project "C++ ToolKit for Smart and Friendly Physics Analysis"
def _get(self, location)
Definition: GaudiAlgs.py:417
DataObjectReadHandle(const std::tuple< Args... > &args, std::index_sequence< Is... >)
T move(T... args)
T * getOrCreate() const
Get object from store or create a new one if it doesn't exist.
T * get() const
Retrieve object from transient data store.
T get(T... args)
std::conditional_t< std::is_base_of_v< DataObject, T >, T, AnyDataWrapper< T > > type
T(*)(const DataObject *) Converter_t
STL class.
DataObjectHandleBase GaudiKernel/DataObjectHandleBase.h.
T begin(T... args)
std::string pythonRepr() const override
auto begin(reverse_wrapper< T > &w)
Definition: reverse.h:47
Useful class for representation of "sequence" of the objects through the range of valid iterators.
Definition: Range.h:95
constexpr static const auto FAILURE
Definition: StatusCode.h:97
Converter_t< Range > select_range_converter(const DataObject *obj)
DataObjectWriteHandle(const DataObjID &k, IDataHandleHolder *owner)
DataObjectWriteHandle(const std::tuple< Args... > &args)
std::remove_cv_t< std::remove_pointer_t< typename T::value_type > > ValueType
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:40
Type
the list of available types for ntuples
Definition: TupleObj.h:89
DataObjectReadHandle(const std::tuple< Args... > &args)
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
DataObjectHandleBase(const DataObjID &k, Gaudi::DataHandle::Mode a, IDataHandleHolder *owner)
DataObjectWriteHandle(const std::tuple< Args... > &args, std::index_sequence< Is... >)