The Gaudi Framework  v40r0 (475e45c1)
IInterface.h
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2025 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 #pragma once
12 
13 #include <Gaudi/Concepts.h>
14 #include <GaudiKernel/Kernel.h>
15 #include <GaudiKernel/StatusCode.h>
16 #include <GaudiKernel/System.h>
17 #include <ostream>
18 #include <type_traits>
19 #include <typeinfo>
20 
22 #define DeclareInterfaceID( iface, major, minor ) \
23  static const InterfaceID& interfaceID() { return iid::interfaceID(); } \
24  using iid = Gaudi::InterfaceId<iface, major, minor>; \
25  using ext_iids = typename iid::iids
26 
38 class GAUDI_API InterfaceID final {
39 public:
41  constexpr InterfaceID( unsigned long id, unsigned long major, unsigned long minor = 0 )
42  : m_id( id ), m_major_ver( major ), m_minor_ver( minor ) {}
44  InterfaceID( const char* name, unsigned long major, unsigned long minor = 0 )
45  : m_id( hash32( name ) ), m_major_ver( major ), m_minor_ver( minor ) {}
47  constexpr unsigned long id() const { return m_id; }
49  constexpr unsigned long majorVersion() const { return m_major_ver; }
51  constexpr unsigned long minorVersion() const { return m_minor_ver; }
55  constexpr bool versionMatch( const InterfaceID& iid ) const {
56  return ( id() == iid.id() && majorVersion() == iid.majorVersion() && minorVersion() >= iid.minorVersion() );
57  }
59  constexpr bool fullMatch( const InterfaceID& iid ) const {
60  return ( id() == iid.id() && majorVersion() == iid.majorVersion() && minorVersion() == iid.minorVersion() );
61  }
63  constexpr bool operator==( const InterfaceID& iid ) const { return fullMatch( iid ); }
65  static unsigned int hash32( const char* key ) {
66  unsigned int hash = 0;
67  for ( const char* k = key; *k; ++k ) {
68  hash += *k;
69  hash += ( hash << 10 );
70  hash ^= ( hash >> 6 );
71  }
72  hash += ( hash << 3 );
73  hash ^= ( hash >> 11 );
74  hash += ( hash << 15 );
75  return hash;
76  }
77 
79  friend std::ostream& operator<<( std::ostream& s, const InterfaceID& id ) {
80  s << "IID_" << id.id();
81  return s;
82  }
83 
84 private:
85  unsigned long m_id;
86  unsigned long m_major_ver;
87  unsigned long m_minor_ver;
88 };
89 
90 namespace Gaudi {
91 
92  template <typename... I>
93  struct interface_list {};
94 
95  namespace meta {
96  // identity T -> type = T; note that id_<T> is a complete type, even if T is not
97  template <typename T>
98  struct id_ {
99  using type = T;
100  };
101 
102  namespace detail {
103  template <typename... Is>
104  struct inherit_from : Is... {};
105 
106  template <typename List, typename I>
107  struct append1 {};
108 
109  // interpose an id_<I> as id_<I> is a complete type, even if I is not... and we need complete
110  // types to inherit from
111  template <typename... Is, typename I>
112  struct append1<interface_list<Is...>, I>
113  : id_<std::conditional_t<std::is_base_of_v<id_<I>, inherit_from<id_<Is>...>>, interface_list<Is...>,
114  interface_list<Is..., I>>> {};
115 
116  template <typename, typename>
117  struct appendN {};
118 
119  template <typename State>
120  struct appendN<interface_list<>, State> : id_<State> {};
121 
122  template <typename... Is, typename I, typename List>
123  struct appendN<interface_list<I, Is...>, List> : appendN<interface_list<Is...>, typename append1<List, I>::type> {
124  };
125  } // namespace detail
126 
127  template <typename... Is>
129  } // namespace meta
130 
131  // interface_list concatenation
132  template <typename... I>
134 
135  // identity
136  template <typename... I>
138 
139  // binary op
140  template <typename... I1, typename... I2>
142  };
143 
144  // induction of binary op
145  template <typename... I1, typename... I2, typename... Others>
146  struct interface_list_cat<interface_list<I1...>, interface_list<I2...>, Others...>
147  : interface_list_cat<interface_list<I1..., I2...>, Others...> {};
148 
149  // append is a special case of concatenation...
150  template <typename... I>
152 
153  template <typename... Is, typename I>
155  : interface_list_cat<interface_list<Is...>, interface_list<I>> {};
156 
157  template <typename... Is>
158  std::vector<std::string> getInterfaceNames( Gaudi::interface_list<Is...> ) {
159  return { Is::name()... };
160  }
161 
162  template <typename... Is, typename P>
163  void* iid_cast( const InterfaceID& tid, Gaudi::interface_list<Is...>, P* ptr ) {
164  const void* target = nullptr;
165  ( ( tid.versionMatch( Is::interfaceID() ) &&
166  ( target = static_cast<typename Is::interface_type const*>( ptr ), true ) ) ||
167  ... );
168  return const_cast<void*>( target );
169  }
170 
174  template <typename INTERFACE, unsigned long majVers, unsigned long minVers>
175  struct InterfaceId final {
177  using interface_type = INTERFACE;
180 
181  static inline std::string name() { return System::typeinfoName( typeid( INTERFACE ) ); }
182  static constexpr unsigned long majorVersion() { return majVers; }
183  static constexpr unsigned long minorVersion() { return minVers; }
184 
185  static inline const std::type_info& TypeInfo() { return typeid( typename iids::type ); }
186 
187  static inline const InterfaceID& interfaceID() {
188  static const InterfaceID s_iid( name().c_str(), majVers, minVers );
189  return s_iid;
190  }
191  };
192 
193  constexpr struct fullMatch_t {
194  template <typename IFACE1, typename IFACE2, unsigned long major1, unsigned long major2, unsigned long minor1,
195  unsigned long minor2>
197  return false;
198  }
199  template <typename IFACE, unsigned long major, unsigned long minor>
201  return true;
202  }
204 
205  constexpr struct majorMatch_t {
206  template <typename IFACE1, typename IFACE2, unsigned long major1, unsigned long major2, unsigned long minor1,
207  unsigned long minor2>
209  return false;
210  }
211  template <typename IFACE, unsigned long major, unsigned long minor1, unsigned long minor2>
213  return true;
214  }
216 } // namespace Gaudi
217 
226 public:
229 
232 
234  static inline const InterfaceID& interfaceID() { return iid::interfaceID(); }
235 
236  template <Gaudi::IsInterface TARGET>
237  TARGET* cast() {
238  if ( auto output = i_cast( TARGET::interfaceID() ) ) { return reinterpret_cast<TARGET*>( output ); }
239  if constexpr ( Gaudi::IsInterface<TARGET> ) {
240  void* tgt = nullptr;
241  queryInterface( TARGET::interfaceID(), &tgt ).ignore();
242  if ( tgt ) {
243  // queryInterface bumps the reference count of the target object, but we should not
244  auto* target = reinterpret_cast<TARGET*>( tgt );
245  // we cannot use release() because we may be called with an object with initial reference count of 0 and that
246  // would delete the object
247  static_cast<const IInterface*>( target )->decRef();
248  return target;
249  }
250  }
251  return nullptr;
252  }
253 
254  template <Gaudi::IsInterface TARGET>
255  TARGET const* cast() const {
256  if ( auto output = i_cast( TARGET::interfaceID() ) ) { return reinterpret_cast<TARGET const*>( output ); }
257  if constexpr ( Gaudi::IsInterface<TARGET> ) {
258  void* tgt = nullptr;
259  const_cast<IInterface*>( this )->queryInterface( TARGET::interfaceID(), &tgt ).ignore();
260  if ( tgt ) {
261  // queryInterface bumps the reference count of the target object, but we should not
262  auto* target = reinterpret_cast<const TARGET*>( tgt );
263  // we cannot use release() because we may be called with an object with initial reference count of 0 and that
264  // would delete the object
265  static_cast<const IInterface*>( target )->decRef();
266  return target;
267  }
268  }
269  return nullptr;
270  }
271 
272  template <typename TARGET>
273  requires( !Gaudi::IsInterface<TARGET> )
274  TARGET* cast() {
275  return dynamic_cast<TARGET*>( this );
276  }
277 
278  template <typename TARGET>
279  requires( !Gaudi::IsInterface<TARGET> )
280  TARGET const* cast() const {
281  return dynamic_cast<TARGET const*>( this );
282  }
283 
285  virtual std::vector<std::string> getInterfaceNames() const = 0;
286 
288  virtual unsigned long addRef() const = 0;
289 
291  virtual unsigned long release() const = 0;
292 
294  virtual unsigned long refCount() const = 0;
295 
297  virtual StatusCode queryInterface( const InterfaceID& ti, void** pp ) = 0;
298 
300  enum class Status : StatusCode::code_t {
302  FAILURE = 0,
304  SUCCESS = 1,
306  NO_INTERFACE,
308  VERSMISMATCH,
310  LAST_ERROR
311  };
312 
314  virtual ~IInterface() = default;
315 
316  // Note: these cannot be protected methods because they may be needed by specializations
317  // that delegate to other instances (like queryInterface does).
318  virtual void const* i_cast( const InterfaceID& ) const = 0;
319 
320  void* i_cast( const InterfaceID& iid ) {
321  return const_cast<void*>( const_cast<const IInterface*>( this )->i_cast( iid ) );
322  }
323 
324 protected:
326  virtual unsigned long decRef() const = 0;
327 };
328 
330 
331 namespace Gaudi {
332  template <typename TARGET>
333  TARGET* Cast( IInterface* i ) {
334  return i ? i->cast<TARGET>() : nullptr;
335  }
336 
337  template <typename TARGET>
338  const TARGET* Cast( const IInterface* i ) {
339  return i ? i->cast<const TARGET>() : nullptr;
340  }
341 } // namespace Gaudi
342 
353 template <class IFace>
354 bool isValidInterface( IFace* i ) {
355  void* ii = nullptr;
356  return i->queryInterface( IFace::interfaceID(), &ii ).isSuccess();
357 }
358 
369 template <class DEST, class SRC>
370 inline DEST** pp_cast( SRC** ptr ) {
371  return reinterpret_cast<DEST**>( ptr );
372 }
373 
375 #include <GaudiKernel/extends.h>
376 #include <GaudiKernel/implements.h>
GaudiPython.Bindings.FAILURE
FAILURE
Definition: Bindings.py:84
extend_interfaces.h
Gaudi::InterfaceId
Class to handle automatically the versioning of the interfaces when they are inheriting from other in...
Definition: IInterface.h:175
InterfaceID::fullMatch
constexpr bool fullMatch(const InterfaceID &iid) const
check full compatibility.
Definition: IInterface.h:59
IInterface::cast
TARGET * cast()
Definition: IInterface.h:237
Gaudi::fullMatch
constexpr struct Gaudi::fullMatch_t fullMatch
IInterface::requires
requires(!Gaudi::IsInterface< TARGET >) TARGET const *cast() const
Definition: IInterface.h:279
Gaudi::InterfaceId::majorVersion
static constexpr unsigned long majorVersion()
Definition: IInterface.h:182
System.h
gaudirun.s
string s
Definition: gaudirun.py:346
Gaudi::meta::detail::appendN
Definition: IInterface.h:117
InterfaceID::InterfaceID
constexpr InterfaceID(unsigned long id, unsigned long major, unsigned long minor=0)
constructor from components
Definition: IInterface.h:41
InterfaceID::m_id
unsigned long m_id
Definition: IInterface.h:85
Gaudi::fullMatch_t
Definition: IInterface.h:193
detail
Definition: HistogramSvc.h:45
Gaudi::interface_list_cat
Definition: IInterface.h:133
IInterface::queryInterface
virtual StatusCode queryInterface(const InterfaceID &ti, void **pp)=0
Set the void** to the pointer to the requested interface of the instance.
Gaudi::InterfaceId::minorVersion
static constexpr unsigned long minorVersion()
Definition: IInterface.h:183
extends.h
IInterface::i_cast
virtual void const * i_cast(const InterfaceID &) const =0
StatusCode::code_t
unsigned long code_t
type of StatusCode value
Definition: StatusCode.h:66
Gaudi::interface_list_append
Definition: IInterface.h:151
System::typeinfoName
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:301
IInterface::addRef
virtual unsigned long addRef() const =0
Increment the reference count of Interface instance.
gaudirun.output
output
Definition: gaudirun.py:521
GaudiPartProp.tests.id
id
Definition: tests.py:111
StatusCode.h
AlgExecState::State
State
Definition: IAlgExecStateSvc.h:23
Gaudi::meta::detail::inherit_from
Definition: IInterface.h:104
InterfaceID::id
constexpr unsigned long id() const
get the interface identifier
Definition: IInterface.h:47
compareOutputFiles.target
target
Definition: compareOutputFiles.py:489
IInterface::Status
Status
Return status.
Definition: IInterface.h:300
IInterface::~IInterface
virtual ~IInterface()=default
Virtual destructor.
Gaudi::InterfaceId::interfaceID
static const InterfaceID & interfaceID()
Definition: IInterface.h:187
StatusCode
Definition: StatusCode.h:64
IInterface::interfaceID
static const InterfaceID & interfaceID()
Return an instance of InterfaceID identifying the interface.
Definition: IInterface.h:234
InterfaceID::m_minor_ver
unsigned long m_minor_ver
Definition: IInterface.h:87
InterfaceID::majorVersion
constexpr unsigned long majorVersion() const
get the major version of the interface
Definition: IInterface.h:49
Gaudi::InterfaceId::interface_type
INTERFACE interface_type
interface type
Definition: IInterface.h:177
IInterface::i_cast
void * i_cast(const InterfaceID &iid)
Definition: IInterface.h:320
InterfaceID::m_major_ver
unsigned long m_major_ver
Definition: IInterface.h:86
InterfaceID::operator==
constexpr bool operator==(const InterfaceID &iid) const
compare operator
Definition: IInterface.h:63
Gaudi::meta::id_< State >::type
State type
Definition: IInterface.h:99
Gaudi::meta::id_
Definition: IInterface.h:98
Gaudi::fullMatch_t::operator()
constexpr bool operator()(InterfaceId< IFACE, major, minor >, InterfaceId< IFACE, major, minor >) const
Definition: IInterface.h:200
Gaudi::InterfaceId::name
static std::string name()
Definition: IInterface.h:181
GaudiPython.Bindings.SUCCESS
SUCCESS
Definition: Bindings.py:83
Gaudi::interface_list
Definition: IInterface.h:93
Gaudi::majorMatch
constexpr struct Gaudi::majorMatch_t majorMatch
Gaudi
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...
Definition: __init__.py:1
pp_cast
DEST ** pp_cast(SRC **ptr)
Small function to be used instead of the construct (void**)&pointer, which produces,...
Definition: IInterface.h:370
InterfaceID::minorVersion
constexpr unsigned long minorVersion() const
get the minor version of the interface
Definition: IInterface.h:51
Gaudi::InterfaceId::TypeInfo
static const std::type_info & TypeInfo()
Definition: IInterface.h:185
gaudirun.type
type
Definition: gaudirun.py:160
Gaudi::majorMatch_t
Definition: IInterface.h:205
Gaudi::fullMatch_t::operator()
constexpr bool operator()(InterfaceId< IFACE1, major1, minor1 >, InterfaceId< IFACE2, major2, minor2 >) const
Definition: IInterface.h:196
STATUSCODE_ENUM_DECL
#define STATUSCODE_ENUM_DECL(ENUM)
Declare an enum to be used as StatusCode value.
Definition: StatusCode.h:286
ConditionsStallTest.name
name
Definition: ConditionsStallTest.py:77
Gaudi::meta::detail::append1
Definition: IInterface.h:107
Gaudi::iid_cast
void * iid_cast(const InterfaceID &tid, Gaudi::interface_list< Is... >, P *ptr)
Definition: IInterface.h:163
IInterface::requires
requires(!Gaudi::IsInterface< TARGET >) TARGET *cast()
Definition: IInterface.h:273
Gaudi::getInterfaceNames
std::vector< std::string > getInterfaceNames(Gaudi::interface_list< Is... >)
Definition: IInterface.h:158
Kernel.h
IInterface
Definition: IInterface.h:225
InterfaceID::versionMatch
constexpr bool versionMatch(const InterfaceID &iid) const
check compatibility.
Definition: IInterface.h:55
InterfaceID::hash32
static unsigned int hash32(const char *key)
Jenkins one-at-time hash function – see https://en.wikipedia.org/wiki/Jenkins_hash_function.
Definition: IInterface.h:65
Concepts.h
IInterface::getInterfaceNames
virtual std::vector< std::string > getInterfaceNames() const =0
Returns a vector of strings containing the names of all the implemented interfaces.
isValidInterface
bool isValidInterface(IFace *i)
Templated function that throws an exception if the version if the interface implemented by the object...
Definition: IInterface.h:354
implements.h
Gaudi::InterfaceId::iids
typename Gaudi::interface_list_append< typename interface_type::ext_iids, InterfaceId >::type iids
List of interfaces.
Definition: IInterface.h:179
Gaudi::majorMatch_t::operator()
constexpr bool operator()(InterfaceId< IFACE1, major1, minor1 >, InterfaceId< IFACE2, major2, minor2 >) const
Definition: IInterface.h:208
IInterface::decRef
virtual unsigned long decRef() const =0
Decrement reference count and return the new reference count.
Gaudi::majorMatch_t::operator()
constexpr bool operator()(InterfaceId< IFACE, major, minor1 >, InterfaceId< IFACE, major, minor2 >) const
Definition: IInterface.h:212
InterfaceID::InterfaceID
InterfaceID(const char *name, unsigned long major, unsigned long minor=0)
constructor from components
Definition: IInterface.h:44
InterfaceID
Definition: IInterface.h:38
IInterface::refCount
virtual unsigned long refCount() const =0
Current reference count.
compareOutputFiles.pp
pp
Definition: compareOutputFiles.py:507
InterfaceID::operator<<
friend std::ostream & operator<<(std::ostream &s, const InterfaceID &id)
ostream operator for InterfaceID. Needed by PluginSvc
Definition: IInterface.h:79
ProduceConsume.key
key
Definition: ProduceConsume.py:84
Gaudi::Cast
TARGET * Cast(IInterface *i)
Definition: IInterface.h:333
GAUDI_API
#define GAUDI_API
Definition: Kernel.h:83
IInterface::release
virtual unsigned long release() const =0
Release Interface instance.
IInterface::cast
TARGET const * cast() const
Definition: IInterface.h:255