File indexing completed on 2025-02-21 10:00:28
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 #if __cplusplus >= 201703L
0086 auto accumulate( Mapper f, std::invoke_result_t<Mapper, const T*> init ) const -> decltype( init ) {
0087 #else
0088 auto accumulate( Mapper f, std::result_of_t<Mapper( const T* )> init ) const -> decltype( init ) {
0089 #endif
0090 return accumulate( f, init, std::plus<>() );
0091 }
0092
0093
0094
0095
0096 template <class Mapper, class BinaryOperation>
0097 #if __cplusplus >= 201703L
0098 auto accumulate( Mapper f, std::invoke_result_t<Mapper, const T*> init, BinaryOperation op ) const
0099 #else
0100 auto accumulate( Mapper f, std::result_of_t<Mapper( const T* )> init, BinaryOperation op ) const
0101 #endif
0102 -> decltype( init ) {
0103 auto lock = std::scoped_lock{ m_ptrs_lock };
0104 return std::accumulate( m_ptrs.begin(), m_ptrs.end(), init, [&f, &op]( const auto& partial, const auto& p ) {
0105 return op( partial, f( p.second ) );
0106 } );
0107 }
0108
0109
0110 template <class F>
0111 void for_each( F f ) const {
0112 auto lock = std::scoped_lock{ m_ptrs_lock };
0113 for ( auto& i : m_ptrs ) f( i.second );
0114 }
0115
0116
0117 template <class F>
0118 void for_each( F f ) {
0119 auto lock = std::scoped_lock{ m_ptrs_lock };
0120 for ( auto& i : m_ptrs ) f( i.second );
0121 }
0122
0123
0124 template <class F>
0125 void for_all( F f ) const {
0126 auto lock = std::scoped_lock{ m_ptrs_lock };
0127 for ( auto& i : m_ptrs ) f( i.first, i.second );
0128 }
0129 template <class F>
0130 void for_all( F f ) {
0131 auto lock = std::scoped_lock{ m_ptrs_lock };
0132 for ( auto& i : m_ptrs ) f( i.first, i.second );
0133 }
0134
0135 void deleteAll() {
0136 for_each( []( T*& p ) {
0137 delete p;
0138 p = nullptr;
0139 } );
0140 }
0141
0142 private:
0143
0144 mutable StorageType m_ptrs;
0145
0146 mutable std::mutex m_ptrs_lock;
0147 };
0148
0149
0150
0151
0152
0153
0154
0155 template <typename T>
0156 class ContextSpecificData {
0157 public:
0158
0159 ContextSpecificData( T proto = {} ) : m_proto( std::move( proto ) ) {}
0160
0161
0162 ~ContextSpecificData() { m_ptr.deleteAll(); }
0163
0164 operator T&() {
0165 if ( !m_ptr ) m_ptr = new T( m_proto );
0166 return *m_ptr;
0167 }
0168
0169 operator T&() const {
0170 if ( !m_ptr ) m_ptr = new T( m_proto );
0171 return *m_ptr;
0172 }
0173
0174
0175 T& operator=( const T& other ) { return (T&)( *this ) = other; }
0176
0177
0178 T accumulate( T init ) const { return accumulate( init, std::plus<>() ); }
0179
0180
0181
0182 template <class T1, class BinaryOperation>
0183 T1 accumulate( T1 init, BinaryOperation op ) const {
0184 return m_ptr.accumulate( []( const T* p ) { return *p; }, init, op );
0185 }
0186
0187
0188 template <class F>
0189 void for_each( F f ) const {
0190 m_ptr.for_each( [&f]( const T* p ) { f( *p ); } );
0191 }
0192
0193
0194 template <class F>
0195 void for_each( F f ) {
0196 m_ptr.for_each( [&f]( T* p ) { f( *p ); } );
0197 }
0198
0199
0200 template <class F>
0201 void for_all( F f ) const {
0202 m_ptr.for_all( [&f]( size_t s, const T* p ) { f( s, *p ); } );
0203 }
0204 template <class F>
0205 void for_all( F f ) {
0206 m_ptr.for_all( [&f]( size_t s, T* p ) { f( s, *p ); } );
0207 }
0208
0209 private:
0210
0211 ContextSpecificData( const ContextSpecificData& ) = delete;
0212
0213
0214 T m_proto = {};
0215
0216 mutable ContextSpecificPtr<T> m_ptr;
0217 };
0218 }
0219 }
0220
0221 #endif