Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/leaf/config/tls_array.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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         static BOOST_LEAF_CFG_TLS_INDEX_TYPE next_() noexcept
0069         {
0070             int idx = ++c_;
0071             BOOST_LEAF_ASSERT(idx > (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX));
0072             BOOST_LEAF_ASSERT(idx < (BOOST_LEAF_CFG_TLS_ARRAY_SIZE));
0073             return idx;
0074         }
0075 
0076     public:
0077 
0078         template <class T>
0079         static BOOST_LEAF_CFG_TLS_INDEX_TYPE next() noexcept
0080         {
0081             return next_(); // Set breakpoint here to monitor TLS index allocation for T.
0082         }
0083     };
0084 
0085     template <class T>
0086     struct BOOST_LEAF_SYMBOL_VISIBLE tls_index
0087     {
0088         static BOOST_LEAF_CFG_TLS_INDEX_TYPE idx;
0089     };
0090 
0091     template <class T>
0092     struct BOOST_LEAF_SYMBOL_VISIBLE alloc_tls_index
0093     {
0094         static BOOST_LEAF_CFG_TLS_INDEX_TYPE const idx;
0095     };
0096 
0097     template <class T>
0098     int index_counter<T>::c_ = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX;
0099 
0100     template <class T>
0101     BOOST_LEAF_CFG_TLS_INDEX_TYPE tls_index<T>::idx = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX;
0102 
0103     template <class T>
0104     BOOST_LEAF_CFG_TLS_INDEX_TYPE const alloc_tls_index<T>::idx = tls_index<T>::idx = index_counter<>::next<T>();
0105 
0106     ////////////////////////////////////////
0107 
0108     template <class T>
0109     T * read_ptr() noexcept
0110     {
0111         int tls_idx = tls_index<T>::idx;
0112         if( tls_idx == (BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX) )
0113             return nullptr;
0114         --tls_idx;
0115         return reinterpret_cast<T *>(read_void_ptr(tls_idx));
0116     }
0117 
0118     template <class T>
0119     void write_ptr( T * p ) noexcept
0120     {
0121         int tls_idx = alloc_tls_index<T>::idx;
0122         --tls_idx;
0123         write_void_ptr(tls_idx, p);
0124         BOOST_LEAF_ASSERT(read_void_ptr(tls_idx) == p);
0125     }
0126 
0127     ////////////////////////////////////////
0128 
0129     template <class Tag>
0130     unsigned read_uint() noexcept
0131     {
0132         static_assert(sizeof(std::intptr_t) >= sizeof(unsigned), "Incompatible tls_array implementation");
0133         return (unsigned) (std::intptr_t) (void *) read_ptr<Tag>();
0134     }
0135 
0136     template <class Tag>
0137     void write_uint( unsigned x ) noexcept
0138     {
0139         static_assert(sizeof(std::intptr_t) >= sizeof(unsigned), "Incompatible tls_array implementation");
0140         write_ptr<Tag>((Tag *) (void *) (std::intptr_t) x);
0141     }
0142 
0143     template <class Tag>
0144     void uint_increment() noexcept
0145     {
0146         write_uint<Tag>(read_uint<Tag>() + 1);
0147     }
0148 
0149     template <class Tag>
0150     void uint_decrement() noexcept
0151     {
0152         write_uint<Tag>(read_uint<Tag>() - 1);
0153     }
0154 }
0155 
0156 } }
0157 
0158 #endif