File indexing completed on 2025-09-17 08:57:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef GAUDIKERNEL_GAUDIHANDLE_H
0012 #define GAUDIKERNEL_GAUDIHANDLE_H
0013
0014
0015 #include <Gaudi/Property.h>
0016 #include <GaudiKernel/GaudiException.h>
0017 #include <GaudiKernel/IInterface.h>
0018 #include <GaudiKernel/System.h>
0019
0020 #include <algorithm>
0021 #include <iostream>
0022 #include <string>
0023 #include <type_traits>
0024 #include <vector>
0025
0026 namespace details {
0027
0028 template <class T>
0029 std::remove_const_t<T>* nonConst( T* p ) {
0030 return const_cast<std::remove_const_t<T>*>( p );
0031 }
0032 }
0033
0034 class GAUDI_API GaudiHandleInfo {
0035 protected:
0036
0037
0038
0039
0040
0041
0042
0043
0044 GaudiHandleInfo( std::string myComponentType, std::string myParentName )
0045 : m_componentType( std::move( myComponentType ) ), m_parentName( std::move( myParentName ) ) {}
0046
0047 public:
0048
0049
0050
0051
0052 virtual ~GaudiHandleInfo() {}
0053
0054
0055
0056 const std::string& componentType() const { return m_componentType; }
0057
0058
0059 const std::string& propertyName() const { return m_propertyName; }
0060
0061
0062 void setPropertyName( std::string propName ) { m_propertyName = std::move( propName ); }
0063
0064
0065 const std::string& parentName() const { return m_parentName; }
0066
0067
0068
0069
0070 virtual std::string pythonPropertyClassName() const = 0;
0071
0072
0073
0074
0075
0076 virtual std::string pythonRepr() const = 0;
0077
0078
0079
0080 friend std::ostream& operator<<( std::ostream& os, const GaudiHandleInfo& handle );
0081
0082 protected:
0083
0084 void setComponentType( std::string componentType ) { m_componentType = std::move( componentType ); }
0085
0086
0087 void setParentName( std::string parent ) { m_parentName = std::move( parent ); }
0088
0089 private:
0090
0091
0092
0093 std::string m_componentType;
0094 std::string m_propertyName;
0095 std::string m_parentName;
0096 };
0097
0098
0099
0100
0101
0102
0103
0104
0105 class GAUDI_API GaudiHandleBase : public GaudiHandleInfo {
0106
0107
0108
0109 protected:
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 GaudiHandleBase( std::string myTypeAndName, std::string myComponentType, std::string myParentName )
0122 : GaudiHandleInfo( std::move( myComponentType ), std::move( myParentName ) ) {
0123 setTypeAndName( std::move( myTypeAndName ) );
0124 }
0125
0126 public:
0127
0128
0129
0130
0131 const std::string& typeAndName() const { return m_typeAndName; }
0132
0133
0134 std::string type() const;
0135
0136
0137 std::string name() const;
0138
0139
0140 bool empty() const { return m_typeAndName.empty(); }
0141
0142
0143 void setTypeAndName( std::string myTypeAndName );
0144
0145
0146 void setName( std::string_view myName );
0147
0148
0149
0150
0151 std::string pythonPropertyClassName() const override;
0152
0153
0154 std::string messageName() const;
0155
0156
0157
0158
0159 std::string pythonRepr() const override;
0160
0161 using PropertyType = GaudiHandleProperty;
0162
0163 private:
0164
0165
0166
0167 std::string m_typeAndName;
0168 };
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 template <class T>
0179 class GAUDI_API GaudiHandle : public GaudiHandleBase {
0180
0181
0182
0183 protected:
0184 GaudiHandle( std::string myTypeAndName, std::string myComponentType, std::string myParentName )
0185 : GaudiHandleBase( std::move( myTypeAndName ), std::move( myComponentType ), std::move( myParentName ) ) {}
0186
0187 public:
0188
0189 template <typename CT = T, typename NCT = std::remove_const_t<T>>
0190 GaudiHandle( const GaudiHandle<NCT>& other,
0191 std::enable_if_t<std::is_const_v<CT> && !std::is_same_v<CT, NCT>>* = nullptr )
0192 : GaudiHandleBase( other ) {
0193 m_pObject = other.get();
0194 if ( m_pObject ) ::details::nonConst( m_pObject.load() )->addRef();
0195 }
0196
0197
0198 GaudiHandle( const GaudiHandle& other ) : GaudiHandleBase( other ) {
0199 m_pObject = other.m_pObject.load();
0200 if ( m_pObject ) ::details::nonConst( m_pObject.load() )->addRef();
0201 }
0202
0203
0204 template <typename CT = T, typename NCT = std::remove_const_t<T>>
0205 std::enable_if_t<std::is_const_v<CT> && !std::is_same_v<CT, NCT>, GaudiHandle&>
0206 operator=( const GaudiHandle<NCT>& other ) {
0207 GaudiHandleBase::operator=( other );
0208
0209 release().ignore();
0210 m_pObject = other.get();
0211
0212 if ( m_pObject ) ::details::nonConst( m_pObject.load() )->addRef();
0213 return *this;
0214 }
0215
0216
0217 GaudiHandle& operator=( const GaudiHandle& other ) {
0218 GaudiHandleBase::operator=( other );
0219
0220 release().ignore();
0221 m_pObject = other.m_pObject.load();
0222
0223 if ( m_pObject ) ::details::nonConst( m_pObject.load() )->addRef();
0224 return *this;
0225 }
0226
0227
0228 StatusCode retrieve() const {
0229
0230
0231 T* p = nullptr;
0232 if ( retrieve( p ).isFailure() ) { return StatusCode::FAILURE; }
0233
0234
0235
0236 T* old = nullptr;
0237 if ( m_pObject.compare_exchange_strong( old, p ) ) { return StatusCode::SUCCESS; }
0238 return release( p );
0239 }
0240
0241
0242 StatusCode release() const {
0243
0244 StatusCode sc = StatusCode::SUCCESS;
0245 if ( m_pObject ) {
0246 sc = release( m_pObject );
0247 m_pObject = nullptr;
0248 }
0249 return sc;
0250 }
0251
0252
0253 bool isValid() const {
0254
0255 return m_pObject || retrieve().isSuccess();
0256 }
0257
0258
0259
0260 operator bool() const {
0261
0262 return isValid();
0263 }
0264
0265
0266 T* get() { return m_pObject; }
0267
0268
0269 std::add_const_t<T>* get() const { return m_pObject; }
0270
0271
0272 bool isSet() const { return get(); }
0273
0274 T& operator*() {
0275 assertObject();
0276 return *m_pObject;
0277 }
0278
0279 T* operator->() {
0280 assertObject();
0281 return m_pObject;
0282 }
0283
0284 std::add_const_t<T>& operator*() const {
0285
0286 assertObject();
0287 return *m_pObject;
0288 }
0289
0290 std::add_const_t<T>* operator->() const {
0291
0292 assertObject();
0293 return m_pObject;
0294 }
0295
0296
0297 std::string getDefaultType() { return System::typeinfoName( typeid( T ) ); }
0298
0299 std::string getDefaultName() {
0300 const auto defName = GaudiHandleBase::type();
0301 return ( defName.empty() ? getDefaultType() : defName );
0302 }
0303
0304 protected:
0305
0306 virtual StatusCode retrieve( T*& ) const = 0;
0307
0308
0309
0310 virtual StatusCode release( T* comp ) const {
0311
0312 ::details::nonConst( comp )->release();
0313 return StatusCode::SUCCESS;
0314 }
0315
0316 private:
0317
0318 void setDefaultTypeAndName() {
0319 const std::string& myType = getDefaultType();
0320 GaudiHandleBase::setTypeAndName( myType + '/' + myType );
0321 }
0322
0323
0324 void setDefaultType() { GaudiHandleBase::setTypeAndName( getDefaultType() ); }
0325
0326
0327
0328 void assertObject() const {
0329 if ( !isValid() ) {
0330 throw GaudiException( "Failed to retrieve " + componentType() + ": " + typeAndName(),
0331 componentType() + " retrieve", StatusCode::FAILURE );
0332 }
0333 }
0334
0335 private:
0336
0337
0338
0339 mutable std::atomic<T*> m_pObject = nullptr;
0340 };
0341
0342
0343
0344
0345
0346
0347
0348 class GAUDI_API GaudiHandleArrayBase : public GaudiHandleInfo {
0349 protected:
0350 GaudiHandleArrayBase( std::string myComponentType, std::string myParentName )
0351 : GaudiHandleInfo( std::move( myComponentType ), std::move( myParentName ) ) {}
0352
0353 public:
0354 using PropertyType = GaudiHandleArrayProperty;
0355 typedef std::vector<GaudiHandleBase*> BaseHandleArray;
0356 typedef std::vector<const GaudiHandleBase*> ConstBaseHandleArray;
0357
0358
0359
0360 bool setTypesAndNames( const std::vector<std::string>& myTypesAndNamesList );
0361
0362
0363
0364 const std::vector<std::string> typesAndNames() const;
0365
0366
0367 const std::vector<std::string> types() const;
0368
0369
0370 const std::vector<std::string> names() const;
0371
0372
0373
0374 const std::vector<std::string> getBaseInfos( auto ( GaudiHandleBase::*pMemFunc )() const ) const;
0375
0376
0377
0378
0379 std::string pythonPropertyClassName() const override;
0380
0381
0382
0383
0384 std::string pythonRepr() const override;
0385
0386
0387
0388
0389 virtual bool push_back( const std::string& myHandleTypeAndName ) = 0;
0390
0391
0392 virtual void clear() = 0;
0393
0394
0395 virtual bool empty() const = 0;
0396
0397
0398
0399 virtual ConstBaseHandleArray getBaseArray() const = 0;
0400
0401
0402
0403 virtual BaseHandleArray getBaseArray() = 0;
0404
0405
0406 virtual bool retrieved() const = 0;
0407 };
0408
0409
0410 template <class T>
0411 class GAUDI_API GaudiHandleArray : public GaudiHandleArrayBase {
0412 public:
0413
0414
0415
0416 typedef std::vector<T> HandleVector;
0417 typedef typename HandleVector::value_type value_type;
0418 typedef typename HandleVector::size_type size_type;
0419 typedef typename HandleVector::reference reference;
0420 typedef typename HandleVector::const_reference const_reference;
0421 typedef typename HandleVector::iterator iterator;
0422 typedef typename HandleVector::const_iterator const_iterator;
0423 typedef typename HandleVector::reverse_iterator reverse_iterator;
0424 typedef typename HandleVector::const_reverse_iterator const_reverse_iterator;
0425
0426 protected:
0427
0428
0429
0430
0431
0432
0433
0434 GaudiHandleArray( const std::vector<std::string>& myTypesAndNamesList, std::string myComponentType,
0435 std::string myParentName )
0436 : GaudiHandleArrayBase( std::move( myComponentType ), std::move( myParentName ) ) {
0437 setTypesAndNames( myTypesAndNamesList );
0438 }
0439
0440
0441
0442
0443
0444 GaudiHandleArray( const std::string& myComponentType, const std::string& myParentName )
0445 : GaudiHandleArrayBase( myComponentType, myParentName ) {}
0446
0447 public:
0448
0449 GaudiHandleArray& operator=( const std::vector<std::string>& myTypesAndNamesList ) {
0450 setTypesAndNames( myTypesAndNamesList );
0451 return *this;
0452 }
0453
0454 GaudiHandleArrayBase::BaseHandleArray getBaseArray() override {
0455 GaudiHandleArrayBase::BaseHandleArray baseArray;
0456 for ( auto& h : m_handleArray ) baseArray.push_back( &h );
0457 return baseArray;
0458 }
0459
0460 GaudiHandleArrayBase::ConstBaseHandleArray getBaseArray() const override {
0461 GaudiHandleArrayBase::ConstBaseHandleArray baseArray;
0462 for ( auto& h : m_handleArray ) baseArray.push_back( &h );
0463 return baseArray;
0464 }
0465
0466
0467
0468
0469 iterator begin() { return m_handleArray.begin(); }
0470
0471 iterator end() { return m_handleArray.end(); }
0472
0473 const_iterator begin() const { return m_handleArray.begin(); }
0474
0475 const_iterator end() const { return m_handleArray.end(); }
0476
0477 const_iterator rbegin() const { return m_handleArray.rbegin(); }
0478
0479 const_iterator rend() const { return m_handleArray.rend(); }
0480
0481 size_type size() const { return m_handleArray.size(); }
0482
0483 void clear() override { m_handleArray.clear(); }
0484
0485 bool empty() const override { return m_handleArray.empty(); }
0486
0487 T& operator[]( int index ) { return m_handleArray[index]; }
0488
0489 const T& operator[]( int index ) const { return m_handleArray[index]; }
0490
0491
0492 T* operator[]( std::string_view name ) {
0493 auto it = std::find_if( begin(), end(), [&]( const_reference r ) { return r.name() == name; } );
0494 return it != end() ? &*it : nullptr;
0495 }
0496
0497
0498 const T* operator[]( std::string_view name ) const {
0499 auto it = std::find_if( begin(), end(), [&]( const_reference r ) { return r.name() == name; } );
0500 return it != end() ? &*it : nullptr;
0501 }
0502
0503
0504
0505 using GaudiHandleArrayBase::push_back;
0506 virtual bool push_back( const T& myHandle ) {
0507 m_handleArray.push_back( myHandle );
0508 return true;
0509 }
0510
0511
0512 StatusCode retrieve() {
0513 StatusCode sc = StatusCode::SUCCESS;
0514 for ( auto& i : *this ) {
0515
0516 if ( i.retrieve().isFailure() ) {
0517 sc = StatusCode::FAILURE;
0518 break;
0519 }
0520 }
0521 if ( sc ) { m_retrieved = true; }
0522 return sc;
0523 }
0524
0525
0526 StatusCode release() {
0527 StatusCode sc = StatusCode::SUCCESS;
0528 for ( auto& i : *this ) {
0529
0530 if ( i.release().isFailure() ) sc = StatusCode::FAILURE;
0531 }
0532 return sc;
0533 }
0534
0535
0536 virtual bool retrieved() const override { return m_retrieved; }
0537
0538 private:
0539
0540
0541
0542 HandleVector m_handleArray;
0543 bool m_retrieved{ false };
0544 };
0545
0546 #endif