The Gaudi Framework  v33r0 (d5ea422b)
IInterface.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 GAUDIKERNEL_IINTERFACE_H
12 #define GAUDIKERNEL_IINTERFACE_H
13 
14 // Include files
15 #include "GaudiKernel/Kernel.h"
16 #include "GaudiKernel/StatusCode.h"
17 #include "GaudiKernel/System.h"
18 #include <ostream>
19 #include <type_traits>
20 #include <typeinfo>
21 
23 #define DeclareInterfaceID( iface, major, minor ) \
24  static const InterfaceID& interfaceID() { return iid::interfaceID(); } \
25  using iid = Gaudi::InterfaceId<iface, major, minor>; \
26  using ext_iids = iid::iids
27 
39 class GAUDI_API InterfaceID final {
40 public:
41 #if defined( GAUDI_V20_COMPAT ) && !defined( G21_NEW_INTERFACES )
42  constexpr InterfaceID( unsigned long lid )
44  : m_id( lid & 0xFFFF ), m_major_ver( ( lid & 0xFF000000 ) >> 24 ), m_minor_ver( ( lid & 0xFF0000 ) >> 16 ) {}
45 #endif
46  constexpr InterfaceID( unsigned long id, unsigned long major, unsigned long minor = 0 )
48  : m_id( id ), m_major_ver( major ), m_minor_ver( minor ) {}
50  InterfaceID( const char* name, unsigned long major, unsigned long minor = 0 )
51  : m_id( hash32( name ) ), m_major_ver( major ), m_minor_ver( minor ) {}
52 #if defined( GAUDI_V20_COMPAT ) && !defined( G21_NEW_INTERFACES )
53  constexpr operator unsigned long() const { return ( m_major_ver << 24 ) + ( m_minor_ver << 16 ) + m_id; }
55 #endif
56  constexpr unsigned long id() const { return m_id; }
59  constexpr unsigned long majorVersion() const { return m_major_ver; }
61  constexpr unsigned long minorVersion() const { return m_minor_ver; }
65  constexpr bool versionMatch( const InterfaceID& iid ) const {
66  return ( id() == iid.id() && majorVersion() == iid.majorVersion() && minorVersion() >= iid.minorVersion() );
67  }
69  constexpr bool fullMatch( const InterfaceID& iid ) const {
70  return ( id() == iid.id() && majorVersion() == iid.majorVersion() && minorVersion() == iid.minorVersion() );
71  }
73  constexpr bool operator==( const InterfaceID& iid ) const { return fullMatch( iid ); }
75  static unsigned int hash32( const char* key ) {
76  unsigned int hash = 0;
77  for ( const char* k = key; *k; ++k ) {
78  hash += *k;
79  hash += ( hash << 10 );
80  hash ^= ( hash >> 6 );
81  }
82  hash += ( hash << 3 );
83  hash ^= ( hash >> 11 );
84  hash += ( hash << 15 );
85  return hash;
86  }
87 
88 private:
89  unsigned long m_id;
90  unsigned long m_major_ver;
91  unsigned long m_minor_ver;
92 };
93 
94 namespace Gaudi {
95 
96  template <typename... I>
97  struct interface_list {};
98 
99  namespace meta {
100  // identity T -> type = T; note that id_<T> is a complete type, even if T is not
101  template <typename T>
102  struct id_ {
103  using type = T;
104  };
105 
106  namespace detail {
107  template <typename... Is>
108  struct inherit_from : Is... {};
109 
110  template <typename List, typename I>
111  struct append1 {};
112 
113  // interpose an id_<I> as id_<I> is a complete type, even if I is not... and we need complete
114  // types to inherit from
115  template <typename... Is, typename I>
116  struct append1<interface_list<Is...>, I>
117  : id_<std::conditional_t<std::is_base_of_v<id_<I>, inherit_from<id_<Is>...>>, interface_list<Is...>,
118  interface_list<Is..., I>>> {};
119 
120  template <typename, typename>
121  struct appendN {};
122 
123  template <typename State>
124  struct appendN<interface_list<>, State> : id_<State> {};
125 
126  template <typename... Is, typename I, typename List>
127  struct appendN<interface_list<I, Is...>, List> : appendN<interface_list<Is...>, typename append1<List, I>::type> {
128  };
129  } // namespace detail
130 
131  template <typename... Is>
133  } // namespace meta
134 
135  // interface_list concatenation
136  template <typename... I>
138 
139  // identity
140  template <typename... I>
142 
143  // binary op
144  template <typename... I1, typename... I2>
146  };
147 
148  // induction of binary op
149  template <typename... I1, typename... I2, typename... Others>
150  struct interface_list_cat<interface_list<I1...>, interface_list<I2...>, Others...>
151  : interface_list_cat<interface_list<I1..., I2...>, Others...> {};
152 
153  // append is a special case of concatenation...
154  template <typename... I>
156 
157  template <typename... Is, typename I>
159  : interface_list_cat<interface_list<Is...>, interface_list<I>> {};
160 
161  // helpers for implementation of interface cast
162  namespace iid_cast_details {
163  template <typename I>
164  constexpr void* void_cast( const I* i ) {
165  return const_cast<I*>( i );
166  }
167 
168  template <typename... Is>
169  struct iid_cast_t;
170 
171  template <>
172  struct iid_cast_t<> {
173  template <typename P>
174  constexpr void* operator()( const InterfaceID&, P* ) const {
175  return nullptr;
176  }
177  };
178 
179  template <typename I, typename... Is>
180  struct iid_cast_t<I, Is...> {
181  template <typename P>
182  inline void* operator()( const InterfaceID& tid, P* ptr ) const {
183  return tid.versionMatch( I::interfaceID() ) ? void_cast<typename I::interface_type>( ptr )
184  : iid_cast_t<Is...>{}( tid, ptr );
185  }
186  };
187  } // namespace iid_cast_details
188 
189  template <typename... Is>
191  return {Is::name()...};
192  }
193 
194  template <typename... Is, typename P>
195  inline void* iid_cast( const InterfaceID& tid, Gaudi::interface_list<Is...>, P* ptr ) {
196  constexpr auto iid_cast_ = iid_cast_details::iid_cast_t<Is...>{};
197  return iid_cast_( tid, ptr );
198  }
199 
203  template <typename INTERFACE, unsigned long majVers, unsigned long minVers>
204  struct InterfaceId final {
206  using interface_type = INTERFACE;
209 
210  static inline std::string name() { return System::typeinfoName( typeid( INTERFACE ) ); }
211  static constexpr unsigned long majorVersion() { return majVers; }
212  static constexpr unsigned long minorVersion() { return minVers; }
213 
214  static inline const std::type_info& TypeInfo() { return typeid( typename iids::type ); }
215 
216  static inline const InterfaceID& interfaceID() {
217  static const InterfaceID s_iid( name().c_str(), majVers, minVers );
218  return s_iid;
219  }
220  };
221 
222  constexpr struct fullMatch_t {
223  template <typename IFACE1, typename IFACE2, unsigned long major1, unsigned long major2, unsigned long minor1,
224  unsigned long minor2>
226  return false;
227  }
228  template <typename IFACE, unsigned long major, unsigned long minor>
230  return true;
231  }
232  } fullMatch{};
233 
234  constexpr struct majorMatch_t {
235  template <typename IFACE1, typename IFACE2, unsigned long major1, unsigned long major2, unsigned long minor1,
236  unsigned long minor2>
238  return false;
239  }
240  template <typename IFACE, unsigned long major, unsigned long minor1, unsigned long minor2>
242  return true;
243  }
244  } majorMatch{};
245 } // namespace Gaudi
246 
255 public:
258 
261 
263  static inline const InterfaceID& interfaceID() { return iid::interfaceID(); }
264 
266  virtual void* i_cast( const InterfaceID& ) const
267 #if defined( GAUDI_V20_COMPAT ) && !defined( G21_NEW_INTERFACES )
268  {
269  return nullptr;
270  }
271 #else
272  = 0;
273 #endif
274 
277 #if defined( GAUDI_V20_COMPAT ) && !defined( G21_NEW_INTERFACES )
278  {
279  return {};
280  }
281 #else
282  = 0;
283 #endif
284 
286  virtual unsigned long addRef() = 0;
287 
289  virtual unsigned long release() = 0;
290 
292  virtual unsigned long refCount() const
293 #if defined( GAUDI_V20_COMPAT ) && !defined( G21_NEW_INTERFACES )
294  {
295  IInterface* ths = const_cast<IInterface*>( this );
296  ths->addRef();
297  return ths->release();
298  } // new method, so we need a default implementation for v20 compatibility
299 #else
300  = 0;
301 #endif
302 
304  virtual StatusCode queryInterface( const InterfaceID& ti, void** pp ) = 0;
305 
307  enum class Status : StatusCode::code_t {
309  FAILURE = 0,
311  SUCCESS = 1,
313  NO_INTERFACE,
315  VERSMISMATCH,
317  LAST_ERROR
318  };
319 
321  virtual ~IInterface() = default;
322 };
323 
325 
326 namespace Gaudi {
328  template <typename TARGET>
329  TARGET* Cast( IInterface* i ) {
330  return reinterpret_cast<TARGET*>( i->i_cast( TARGET::interfaceID() ) );
331  }
334  template <typename TARGET>
335  const TARGET* Cast( const IInterface* i ) {
336  return reinterpret_cast<const TARGET*>( i->i_cast( TARGET::interfaceID() ) );
337  }
338 } // namespace Gaudi
339 
350 template <class I>
351 bool isValidInterface( I* i ) {
352  void* ii = nullptr;
353  ;
354  StatusCode sc = i->queryInterface( I::interfaceID(), &ii );
355  return sc.isSuccess();
356 }
357 
358 //#ifdef GAUDI_V20_COMPAT
361  s << "IID_" << id.id();
362  return s;
363 }
364 //#endif
365 
376 template <class DEST, class SRC>
377 inline DEST** pp_cast( SRC** ptr ) {
378  return reinterpret_cast<DEST**>( ptr );
379 }
380 
382 #include "GaudiKernel/extends.h"
383 #include "GaudiKernel/implements.h"
384 
385 #endif // GAUDIKERNEL_IINTERFACE_H
std::ostream & operator<<(std::ostream &s, const InterfaceID &id)
ostream operator for InterfaceID. Needed by PluginSvc
Definition: IInterface.h:360
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:308
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:75
unsigned long m_id
Definition: IInterface.h:89
constexpr struct Gaudi::majorMatch_t majorMatch
constexpr bool fullMatch(const InterfaceID &iid) const
check full compatibility.
Definition: IInterface.h:69
void * operator()(const InterfaceID &tid, P *ptr) const
Definition: IInterface.h:182
constexpr unsigned long id() const
get the interface identifier
Definition: IInterface.h:57
bool isValidInterface(I *i)
Templated function that throws an exception if the version if the interface implemented by the object...
Definition: IInterface.h:351
State
Allowed states for classes implementing the state machine (ApplicationMgr, Algorithm,...
Definition: StateMachine.h:22
INTERFACE interface_type
interface type
Definition: IInterface.h:206
static constexpr unsigned long majorVersion()
Definition: IInterface.h:211
Class to handle automatically the versioning of the interfaces when they are inheriting from other in...
Definition: IInterface.h:204
constexpr void * operator()(const InterfaceID &, P *) const
Definition: IInterface.h:174
DEST ** pp_cast(SRC **ptr)
Small function to be used instead of the construct (void**)&pointer, which produces,...
Definition: IInterface.h:377
constexpr unsigned long majorVersion() const
get the major version of the interface
Definition: IInterface.h:59
STL class.
constexpr bool versionMatch(const InterfaceID &iid) const
check compatibility.
Definition: IInterface.h:65
virtual void * i_cast(const InterfaceID &) const =0
main cast function
Interface ID class.
Definition: IInterface.h:39
unsigned long m_minor_ver
Definition: IInterface.h:91
#define STATUSCODE_ENUM_DECL(ENUM)
Declare an enum to be used as StatusCode value.
Definition: StatusCode.h:333
TupleObj.h GaudiAlg/TupleObj.h namespace with few technical implementations.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:61
Definition of the basic interface.
Definition: IInterface.h:254
constexpr bool operator()(InterfaceId< IFACE1, major1, minor1 >, InterfaceId< IFACE2, major2, minor2 >) const
Definition: IInterface.h:225
constexpr struct Gaudi::fullMatch_t fullMatch
Status
Return status.
Definition: IInterface.h:307
bool isSuccess() const
Definition: StatusCode.h:361
static std::string name()
Definition: IInterface.h:210
constexpr bool operator()(InterfaceId< IFACE, major, minor >, InterfaceId< IFACE, major, minor >) const
Definition: IInterface.h:229
static constexpr unsigned long minorVersion()
Definition: IInterface.h:212
unsigned long m_major_ver
Definition: IInterface.h:90
virtual unsigned long release()=0
Release Interface instance.
constexpr bool operator==(const InterfaceID &iid) const
compare operator
Definition: IInterface.h:73
static const InterfaceID & interfaceID()
Definition: IInterface.h:216
constexpr bool operator()(InterfaceId< IFACE, major, minor1 >, InterfaceId< IFACE, major, minor2 >) const
Definition: IInterface.h:241
string s
Definition: gaudirun.py:328
virtual unsigned long addRef()=0
Increment the reference count of Interface instance.
Gaudi::interface_list< iid > ext_iids
Extra interfaces.
Definition: IInterface.h:260
std::vector< std::string > getInterfaceNames(Gaudi::interface_list< Is... >)
Definition: IInterface.h:190
constexpr void * void_cast(const I *i)
Definition: IInterface.h:164
constexpr unsigned long minorVersion() const
get the minor version of the interface
Definition: IInterface.h:61
TARGET * Cast(IInterface *i)
Cast a IInterface pointer to an IInterface specialization (TARGET).
Definition: IInterface.h:329
InterfaceID(const char *name, unsigned long major, unsigned long minor=0)
constructor from components
Definition: IInterface.h:50
void * iid_cast(const InterfaceID &tid, Gaudi::interface_list< Is... >, P *ptr)
Definition: IInterface.h:195
#define GAUDI_API
Definition: Kernel.h:81
constexpr bool operator()(InterfaceId< IFACE1, major1, minor1 >, InterfaceId< IFACE2, major2, minor2 >) const
Definition: IInterface.h:237
STL class.
static const InterfaceID & interfaceID()
Return an instance of InterfaceID identifying the interface.
Definition: IInterface.h:263
typename Gaudi::interface_list_append< typename interface_type::ext_iids, InterfaceId >::type iids
List of interfaces.
Definition: IInterface.h:208
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
unsigned long code_t
type of StatusCode value
Definition: StatusCode.h:63
Gaudi::InterfaceId< IInterface, 0, 0 > iid
Interface ID.
Definition: IInterface.h:257
static const std::type_info & TypeInfo()
Definition: IInterface.h:214