The Gaudi Framework  v33r1 (b1225454)
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  auto _first = reinterpret_cast<typename Range::const_iterator*>( &first );
40  auto _last = reinterpret_cast<typename Range::const_iterator*>( &last );
41  return Range( *_first, *_last );
42  }
43 
44  template <typename ValueType, typename Range = Gaudi::Range_<typename ValueType::ConstVector>>
46  using Selection = typename ValueType::Selection;
47  auto sel = dynamic_cast<const Selection*>( obj );
48  if ( sel ) return &make_range<Range, typename ValueType::Selection>;
49  auto con = dynamic_cast<std::add_const_t<typename ValueType::Container>*>( obj );
50  if ( con ) return &make_range<Range, typename ValueType::Container>;
51  return nullptr;
52  }
53 
54  template <typename T>
55  bool verifyType( const DataObject* dataObj ) {
56  using Type = std::add_const_t<T>;
57  assert( dataObj != nullptr );
58  auto obj = dynamic_cast<Type*>( dataObj );
59  bool ok = ( obj != nullptr );
60  if ( !ok ) {
61  const auto* registry = dataObj->registry();
62  throw GaudiException( "The type expected for " + registry->identifier() + " is " +
63  System::typeinfoName( typeid( Type ) ) +
64  " and is different from the one of the object in the store which is " +
65  System::typeinfoName( typeid( *dataObj ) ) + ".",
66  "Wrong DataObjectType", StatusCode::FAILURE );
67  }
68  assert( obj == static_cast<Type*>( dataObj ) );
69  return ok;
70  }
71 
72  template <typename T>
73  struct Payload_helper {
74  using type = std::conditional_t<std::is_base_of_v<DataObject, T>, T, AnyDataWrapper<std::remove_const_t<T>>>;
75  };
76  template <typename T>
77  struct Payload_helper<Gaudi::Range_<T>> {
79  };
80  template <typename T>
81  struct Payload_helper<Gaudi::NamedRange_<T>> {
83  };
84 
85  template <typename T>
87 } // namespace details
88 
89 //---------------------------------------------------------------------------
90 
101 //---------------------------------------------------------------------------
102 
103 template <typename T>
104 class DataObjectHandle : public DataObjectHandleBase {
105 public:
107 
111  T* get() const { return get( true ); }
112 
117  T* getIfExists() const { return get( false ); }
118 
122  bool exist() const { return get( false ) != nullptr; }
123 
127  T* getOrCreate() const;
128 
132  T* put( std::unique_ptr<T> object ) const;
133 
134  // [[deprecated("please pass a std::unique_ptr instead of a raw pointer")]]
135  T* put( T* object ) const { return put( std::unique_ptr<T>( object ) ); }
136 
137  std::string pythonRepr() const override {
138  auto repr = DataObjectHandleBase::pythonRepr();
139  boost::replace_all( repr, default_type, System::typeinfoName( typeid( T ) ) );
140  return repr;
141  }
142 
143 private:
144  T* get( bool mustExist ) const;
145  mutable bool m_goodType = false;
146 };
147 
148 //---------------------------------------------------------------------------
149 //
157 template <typename T>
158 T* DataObjectHandle<T>::get( bool mustExist ) const {
159  auto dataObj = fetch();
160  if ( UNLIKELY( !dataObj ) ) {
161  if ( mustExist ) { // Problems in getting from the store
162  throw GaudiException( "Cannot retrieve " + objKey() + " from transient store.",
163  m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
164  }
165  return nullptr;
166  }
167  if ( UNLIKELY( !m_goodType ) ) m_goodType = ::details::verifyType<T>( dataObj );
168  return static_cast<T*>( dataObj );
169 }
170 
171 //---------------------------------------------------------------------------
172 template <typename T>
174  assert( m_init );
175  StatusCode rc = m_EDS->registerObject( objKey(), objectp.get() );
176  if ( !rc.isSuccess() ) {
177  throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<T>::put", StatusCode::FAILURE );
178  }
179  return objectp.release();
180 }
181 
182 //---------------------------------------------------------------------------
183 template <typename T>
185  T* obj = get( false );
186  return obj ? obj : put( std::make_unique<T>() );
187 }
188 
189 //---------------------------------------------------------------------------
191 
192 template <typename T>
193 class DataObjectHandle<Gaudi::Range_<T>> : public DataObjectHandleBase {
194 public:
195  using ValueType = std::remove_cv_t<std::remove_pointer_t<typename T::value_type>>;
197 
199 
203  Range get() const;
204 
205  std::string pythonRepr() const override {
206  auto repr = DataObjectHandleBase::pythonRepr();
207  boost::replace_all( repr, default_type, System::typeinfoName( typeid( Gaudi::Range_<T> ) ) );
208  return repr;
209  }
210 
211 private:
212  mutable ::details::Converter_t<Range> m_converter = nullptr;
213 };
214 
215 template <typename ValueType>
216 auto DataObjectHandle<Gaudi::Range_<ValueType>>::get() const -> Range {
217  auto dataObj = fetch();
218  if ( UNLIKELY( !dataObj ) ) {
219  throw GaudiException( "Cannot retrieve " + objKey() + " from transient store.",
220  m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
221  }
222  if ( UNLIKELY( !m_converter ) ) {
223  m_converter = ::details::select_range_converter<ValueType>( dataObj );
224  if ( !m_converter ) {
225  throw GaudiException( "The type requested for " + objKey() + " (" + System::typeinfoName( typeid( ValueType ) ) +
226  ")" + " cannot be obtained from object in event store" + " (" +
227  System::typeinfoName( typeid( *dataObj ) ) + ").",
228  "Wrong DataObjectType", StatusCode::FAILURE );
229  }
230  }
231  return ( *m_converter )( dataObj );
232 }
233 
234 //---------------------------------------------------------------------------
236 
237 template <typename T>
238 class DataObjectHandle<Gaudi::NamedRange_<T>> : public DataObjectHandleBase {
239 public:
240  using ValueType = std::remove_cv_t<std::remove_pointer_t<typename T::value_type>>;
242 
244 
248  Range get() const;
249 
250  std::string pythonRepr() const override {
251  auto repr = DataObjectHandleBase::pythonRepr();
252  boost::replace_all( repr, default_type, System::typeinfoName( typeid( Gaudi::NamedRange_<T> ) ) );
253  return repr;
254  }
255 
256 private:
257  mutable ::details::Converter_t<Range> m_converter = nullptr;
258 };
259 
260 template <typename ValueType>
262  auto dataObj = fetch();
263  if ( UNLIKELY( !dataObj ) ) {
264  throw GaudiException( "Cannot retrieve " + objKey() + " from transient store.",
265  m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
266  }
267  if ( UNLIKELY( !m_converter ) ) {
268  m_converter = ::details::select_range_converter<ValueType, Range>( dataObj );
269  if ( !m_converter ) {
270  throw GaudiException( "The type requested for " + objKey() + " (" + System::typeinfoName( typeid( ValueType ) ) +
271  ")" + " cannot be obtained from object in event store" + " (" +
272  System::typeinfoName( typeid( *dataObj ) ) + ").",
273  "Wrong DataObjectType", StatusCode::FAILURE );
274  }
275  }
276  return ( *m_converter )( dataObj );
277 }
278 
279 //---------------------------------------------------------------------------
281 template <typename T>
283 public:
285 
289  T* get() const { return &_get( true )->getData(); }
290  T* getIfExists() const {
291  auto data = _get( false );
292  return data ? &data->getData() : nullptr;
293  }
294 
298  const T* put( T&& object ) const;
299 
303  std::optional<std::size_t> size() const { return _get()->size(); }
304 
305  std::string pythonRepr() const override {
306  auto repr = DataObjectHandleBase::pythonRepr();
307  boost::replace_all( repr, default_type, System::typeinfoName( typeid( T ) ) );
308  return repr;
309  }
310 
311 private:
312  AnyDataWrapper<T>* _get( bool mustExist ) const;
313  mutable bool m_goodType = false;
314 };
315 
316 //---------------------------------------------------------------------------
317 
318 template <typename T>
320  auto obj = fetch();
321  if ( UNLIKELY( !obj ) ) {
322  if ( mustExist ) {
323  throw GaudiException( "Cannot retrieve " + objKey() + " from transient store.",
324  m_owner ? owner()->name() : "no owner", StatusCode::FAILURE );
325 
326  } else {
327  return nullptr;
328  }
329  }
330  if ( UNLIKELY( !m_goodType ) ) m_goodType = ::details::verifyType<AnyDataWrapper<T>>( obj );
331  return static_cast<AnyDataWrapper<T>*>( obj );
332 }
333 
334 //---------------------------------------------------------------------------
335 
336 template <typename T>
337 const T* DataObjectHandle<AnyDataWrapper<T>>::put( T&& obj ) const {
338  assert( m_init );
339  auto objectp = std::make_unique<AnyDataWrapper<T>>( std::move( obj ) );
340  StatusCode rc = m_EDS->registerObject( objKey(), objectp.get() );
341  if ( rc.isFailure() ) {
342  throw GaudiException( "Error in put of " + objKey(), "DataObjectHandle<T>::put", StatusCode::FAILURE );
343  }
344  return &objectp.release()->getData();
345 }
346 
347 //---------------------------- user-facing interface ----------
348 
349 template <typename T>
350 class DataObjectReadHandle : public DataObjectHandle<::details::Payload_t<T>> {
351  template <typename... Args, std::size_t... Is>
352  DataObjectReadHandle( const std::tuple<Args...>& args, std::index_sequence<Is...> )
353  : DataObjectReadHandle( std::get<Is>( args )... ) {}
354 
355 public:
358 
361  template <typename OWNER, typename K, typename = std::enable_if_t<std::is_base_of_v<IProperty, OWNER>>>
362  DataObjectReadHandle( OWNER* owner, std::string propertyName, const K& key = {}, std::string doc = "" )
364  std::move( doc ) ) {}
365 
366  template <typename... Args>
368  : DataObjectReadHandle( args, std::index_sequence_for<Args...>{} ) {}
369 };
370 
371 template <typename T>
372 class DataObjectWriteHandle : public DataObjectHandle<::details::Payload_t<T>> {
373  template <typename... Args, std::size_t... Is>
374  DataObjectWriteHandle( const std::tuple<Args...>& args, std::index_sequence<Is...> )
375  : DataObjectWriteHandle( std::get<Is>( args )... ) {}
376 
377 public:
380 
383  template <typename OWNER, typename K, typename = std::enable_if_t<std::is_base_of_v<IProperty, OWNER>>>
384  DataObjectWriteHandle( OWNER* owner, std::string propertyName, const K& key = {}, std::string doc = "" )
386  std::move( doc ) ) {}
387 
388  template <typename... Args>
390  : DataObjectWriteHandle( args, std::index_sequence_for<Args...>{} ) {}
391 };
392 
393 #endif
DataObjectWriteHandle(OWNER *owner, std::string propertyName, const K &key={}, std::string doc="")
Autodeclaring constructor with property name, mode, key and documentation.
std::conditional_t< std::is_base_of_v< DataObject, T >, T, AnyDataWrapper< std::remove_const_t< T > >> type
#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)
std::remove_cv_t< std::remove_pointer_t< typename T::value_type > > ValueType
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.
Gaudi::NamedRange_< typename ValueType::ConstVector > Range
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)
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:101
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... >)