Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:44:51

0001 #ifndef BOOST_LEAF_CONFIG_TLS_ARRAY_HPP_INCLUDED
0002 #define BOOST_LEAF_CONFIG_TLS_ARRAY_HPP_INCLUDED
0003 
0004 // Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc.
0005 // Copyright (c) 2022 Khalil Estell
0006 
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 // LEAF requires thread local storage support for pointers and for uin32_t values.
0011 
0012 // This header implements thread local storage for pointers and for unsigned int
0013 // values for platforms that support thread local pointers by index.
0014 
0015 namespace boost { namespace leaf {
0016 
0017 namespace tls
0018 {
0019     // The TLS support defined in this header requires the following two
0020     // functions to be defined elsewhere:
0021     void * read_void_ptr( int tls_index ) noexcept;
0022     void write_void_ptr( int tls_index, void * ) noexcept;
0023 }
0024 
0025 } }
0026 
0027 ////////////////////////////////////////
0028 
0029 #include <limits>
0030 #include <atomic>
0031 #include <cstdint>
0032 #include <type_traits>
0033 
0034 #ifndef BOOST_LEAF_CFG_TLS_INDEX_TYPE
0035 #   define BOOST_LEAF_CFG_TLS_INDEX_TYPE unsigned char
0036 #endif
0037 
0038 #ifndef BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX
0039 #   define BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX 0
0040 #endif
0041 
0042 static_assert((BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX) >= 0,
0043     "Bad BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX");
0044 
0045 #ifdef BOOST_LEAF_CFG_TLS_ARRAY_SIZE
0046     static_assert((BOOST_LEAF_CFG_TLS_ARRAY_SIZE) > (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX),
0047         "Bad BOOST_LEAF_CFG_TLS_ARRAY_SIZE");
0048     static_assert((BOOST_LEAF_CFG_TLS_ARRAY_SIZE) - 1 <= std::numeric_limits<BOOST_LEAF_CFG_TLS_INDEX_TYPE>::max(),
0049         "Bad BOOST_LEAF_CFG_TLS_ARRAY_SIZE");
0050 #endif
0051 
0052 ////////////////////////////////////////
0053 
0054 namespace boost { namespace leaf {
0055 
0056 namespace leaf_detail
0057 {
0058     using atomic_unsigned_int = std::atomic<unsigned int>;
0059 }
0060 
0061 namespace tls
0062 {
0063     template <class=void>
0064     class BOOST_LEAF_SYMBOL_VISIBLE index_counter
0065     {
0066         static int c_;
0067 
0068     public:
0069 
0070         static BOOST_LEAF_CFG_TLS_INDEX_TYPE next()
0071         {
0072             int idx = ++c_;
0073             BOOST_LEAF_ASSERT(idx > (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX));
0074             BOOST_LEAF_ASSERT(idx < (BOOST_LEAF_CFG_TLS_ARRAY_SIZE));
0075             return idx;
0076         }
0077     };
0078 
0079     template <class T>
0080     struct BOOST_LEAF_SYMBOL_VISIBLE tls_index
0081     {
0082         static BOOST_LEAF_CFG_TLS_INDEX_TYPE idx;
0083     };
0084 
0085     template <class T>
0086     struct BOOST_LEAF_SYMBOL_VISIBLE alloc_tls_index
0087     {
0088         static BOOST_LEAF_CFG_TLS_INDEX_TYPE const idx;
0089     };
0090 
0091     template <class T>
0092     int index_counter<T>::c_ = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX;
0093 
0094     template <class T>
0095     BOOST_LEAF_CFG_TLS_INDEX_TYPE tls_index<T>::idx = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX;
0096 
0097     template <class T>
0098     BOOST_LEAF_CFG_TLS_INDEX_TYPE const alloc_tls_index<T>::idx = tls_index<T>::idx = index_counter<>::next();
0099 
0100     ////////////////////////////////////////
0101 
0102     template <class T>
0103     T * read_ptr() noexcept
0104     {
0105         int tls_idx = tls_index<T>::idx;
0106         if( tls_idx == (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX) )
0107             return nullptr;
0108         --tls_idx;
0109         return reinterpret_cast<T *>(read_void_ptr(tls_idx));
0110     }
0111 
0112     template <class T>
0113     void write_ptr( T * p ) noexcept
0114     {
0115         int tls_idx = alloc_tls_index<T>::idx;
0116         --tls_idx;
0117         write_void_ptr(tls_idx, p);
0118         BOOST_LEAF_ASSERT(read_void_ptr(tls_idx) == p);
0119     }
0120 
0121     ////////////////////////////////////////
0122 
0123     template <class Tag>
0124     unsigned read_uint() noexcept
0125     {
0126         static_assert(sizeof(std::intptr_t) >= sizeof(unsigned), "Incompatible tls_array implementation");
0127         return (unsigned) (std::intptr_t) (void *) read_ptr<Tag>();
0128     }
0129 
0130     template <class Tag>
0131     void write_uint( unsigned x ) noexcept
0132     {
0133         static_assert(sizeof(std::intptr_t) >= sizeof(unsigned), "Incompatible tls_array implementation");
0134         write_ptr<Tag>((Tag *) (void *) (std::intptr_t) x);
0135     }
0136 
0137     template <class Tag>
0138     void uint_increment() noexcept
0139     {
0140         write_uint<Tag>(read_uint<Tag>() + 1);
0141     }
0142 
0143     template <class Tag>
0144     void uint_decrement() noexcept
0145     {
0146         write_uint<Tag>(read_uint<Tag>() - 1);
0147     }
0148 }
0149 
0150 } }
0151 
0152 #endif