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