File indexing completed on 2025-09-15 08:57:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef _GAUDI_CONTEXTSPECIFICPTR_H_
0012 #define _GAUDI_CONTEXTSPECIFICPTR_H_
0013
0014 #include <functional>
0015 #include <mutex>
0016 #include <numeric>
0017 #include <type_traits>
0018 #include <unordered_map>
0019
0020
0021 #include <GaudiKernel/Kernel.h>
0022 #include <GaudiKernel/ThreadLocalContext.h>
0023
0024 class EventContext;
0025
0026 namespace Gaudi {
0027 namespace Hive {
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 template <typename T>
0040 class ContextSpecificPtr {
0041 private:
0042
0043 typedef std::unordered_map<ContextIdType, T*> StorageType;
0044
0045 public:
0046
0047 T* get() const {
0048 auto lock = std::scoped_lock{ m_ptrs_lock };
0049 return m_ptrs[currentContextId()];
0050 }
0051
0052 T*& set( T* ptr ) {
0053 auto lock = std::scoped_lock{ m_ptrs_lock };
0054 return m_ptrs[currentContextId()] = ptr;
0055 }
0056
0057
0058 T*& operator=( T* ptr ) { return set( ptr ); }
0059
0060
0061 bool isValid() const { return get(); }
0062
0063
0064 operator bool() const { return isValid(); }
0065
0066
0067 bool operator==( T* rhs ) const { return get() == rhs; }
0068
0069
0070 T& operator*() { return *get(); }
0071 const T& operator*() const { return *get(); }
0072 T* operator->() { return get(); }
0073 const T* operator->() const { return get(); }
0074
0075
0076
0077
0078
0079 void clear() { m_ptrs.clear(); }
0080
0081
0082
0083
0084 template <class Mapper>
0085 auto accumulate( Mapper f, std::invoke_result_t<Mapper, const T*> init ) const -> decltype( init ) {
0086 return accumulate( f, init, std::plus<>() );
0087 }
0088
0089
0090
0091
0092 template <class Mapper, class BinaryOperation>
0093 auto accumulate( Mapper f, std::invoke_result_t<Mapper, const T*> init, BinaryOperation op ) const
0094 -> decltype( init ) {
0095 auto lock = std::scoped_lock{ m_ptrs_lock };
0096 return std::accumulate( m_ptrs.begin(), m_ptrs.end(), init, [&f, &op]( const auto& partial, const auto& p ) {
0097 return op( partial, f( p.second ) );
0098 } );
0099 }
0100
0101
0102 template <class F>
0103 void for_each( F f ) const {
0104 auto lock = std::scoped_lock{ m_ptrs_lock };
0105 for ( auto& i : m_ptrs ) f( i.second );
0106 }
0107
0108
0109 template <class F>
0110 void for_each( F f ) {
0111 auto lock = std::scoped_lock{ m_ptrs_lock };
0112 for ( auto& i : m_ptrs ) f( i.second );
0113 }
0114
0115
0116 template <class F>
0117 void for_all( F f ) const {
0118 auto lock = std::scoped_lock{ m_ptrs_lock };
0119 for ( auto& i : m_ptrs ) f( i.first, i.second );
0120 }
0121 template <class F>
0122 void for_all( F f ) {
0123 auto lock = std::scoped_lock{ m_ptrs_lock };
0124 for ( auto& i : m_ptrs ) f( i.first, i.second );
0125 }
0126
0127 void deleteAll() {
0128 for_each( []( T*& p ) {
0129 delete p;
0130 p = nullptr;
0131 } );
0132 }
0133
0134 private:
0135
0136 mutable StorageType m_ptrs;
0137
0138 mutable std::mutex m_ptrs_lock;
0139 };
0140
0141
0142
0143
0144
0145
0146
0147 template <typename T>
0148 class ContextSpecificData {
0149 public:
0150
0151 ContextSpecificData( T proto = {} ) : m_proto( std::move( proto ) ) {}
0152
0153
0154 ~ContextSpecificData() { m_ptr.deleteAll(); }
0155
0156 operator T&() {
0157 if ( !m_ptr ) m_ptr = new T( m_proto );
0158 return *m_ptr;
0159 }
0160
0161 operator T&() const {
0162 if ( !m_ptr ) m_ptr = new T( m_proto );
0163 return *m_ptr;
0164 }
0165
0166
0167 T& operator=( const T& other ) { return (T&)( *this ) = other; }
0168
0169
0170 T accumulate( T init ) const { return accumulate( init, std::plus<>() ); }
0171
0172
0173
0174 template <class T1, class BinaryOperation>
0175 T1 accumulate( T1 init, BinaryOperation op ) const {
0176 return m_ptr.accumulate( []( const T* p ) { return *p; }, init, op );
0177 }
0178
0179
0180 template <class F>
0181 void for_each( F f ) const {
0182 m_ptr.for_each( [&f]( const T* p ) { f( *p ); } );
0183 }
0184
0185
0186 template <class F>
0187 void for_each( F f ) {
0188 m_ptr.for_each( [&f]( T* p ) { f( *p ); } );
0189 }
0190
0191
0192 template <class F>
0193 void for_all( F f ) const {
0194 m_ptr.for_all( [&f]( size_t s, const T* p ) { f( s, *p ); } );
0195 }
0196 template <class F>
0197 void for_all( F f ) {
0198 m_ptr.for_all( [&f]( size_t s, T* p ) { f( s, *p ); } );
0199 }
0200
0201 private:
0202
0203 ContextSpecificData( const ContextSpecificData& ) = delete;
0204
0205
0206 T m_proto = {};
0207
0208 mutable ContextSpecificPtr<T> m_ptr;
0209 };
0210 }
0211 }
0212
0213 #endif