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