LCOV - code coverage report
Current view: top level - include/boost/corosio/detail - thread_local_ptr.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 5 5
Test Date: 2026-02-16 16:21:08 Functions: 100.0 % 8 8

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : //
       4                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6                 : //
       7                 : // Official repository: https://github.com/cppalliance/corosio
       8                 : //
       9                 : 
      10                 : #ifndef BOOST_COROSIO_DETAIL_THREAD_LOCAL_PTR_HPP
      11                 : #define BOOST_COROSIO_DETAIL_THREAD_LOCAL_PTR_HPP
      12                 : 
      13                 : #include <boost/corosio/detail/config.hpp>
      14                 : 
      15                 : #include <type_traits>
      16                 : 
      17                 : // Detect thread-local storage mechanism
      18                 : #if !defined(BOOST_COROSIO_TLS_KEYWORD)
      19                 : #if defined(_MSC_VER)
      20                 : #define BOOST_COROSIO_TLS_KEYWORD __declspec(thread)
      21                 : #elif defined(__GNUC__) || defined(__clang__)
      22                 : #define BOOST_COROSIO_TLS_KEYWORD __thread
      23                 : #endif
      24                 : #endif
      25                 : 
      26                 : namespace boost::corosio::detail {
      27                 : 
      28                 : /** A thread-local pointer.
      29                 : 
      30                 :     This class provides thread-local storage for a pointer to T.
      31                 :     Each thread has its own independent pointer value, initially
      32                 :     nullptr. The user is responsible for managing the lifetime
      33                 :     of the pointed-to objects.
      34                 : 
      35                 :     The storage is static per type T. All instances of
      36                 :     `thread_local_ptr<T>` share the same underlying slot.
      37                 : 
      38                 :     The implementation uses the most efficient available mechanism:
      39                 :     1. Compiler keyword (__declspec(thread) or __thread) - enforces POD
      40                 :     2. C++11 thread_local (fallback)
      41                 : 
      42                 :     @tparam T The pointed-to type.
      43                 : 
      44                 :     @par Declaration
      45                 : 
      46                 :     Typically declared at namespace or class scope. The object
      47                 :     is stateless, so local variables work but are redundant.
      48                 : 
      49                 :     @code
      50                 :     // Recommended: namespace scope
      51                 :     namespace {
      52                 :     thread_local_ptr<session> current_session;
      53                 :     }
      54                 : 
      55                 :     // Also works: static class member
      56                 :     class server {
      57                 :         static thread_local_ptr<request> current_request_;
      58                 :     };
      59                 : 
      60                 :     // Works but unusual: local variable (still accesses static storage)
      61                 :     void foo() {
      62                 :         thread_local_ptr<context> ctx;  // same slot on every call
      63                 :         ctx = new context();
      64                 :     }
      65                 :     @endcode
      66                 : 
      67                 :     @note The user is responsible for deleting pointed-to objects
      68                 :     before threads exit to avoid memory leaks.
      69                 : */
      70                 : template<class T>
      71                 : class thread_local_ptr;
      72                 : 
      73                 : 
      74                 : #if defined(BOOST_COROSIO_TLS_KEYWORD)
      75                 : 
      76                 : // Use compiler-specific keyword (__declspec(thread) or __thread)
      77                 : // Most efficient: static linkage, no dynamic init, enforces POD
      78                 : 
      79                 : template<class T>
      80                 : class thread_local_ptr
      81                 : {
      82                 :     static BOOST_COROSIO_TLS_KEYWORD T* ptr_;
      83                 : 
      84                 : public:
      85                 :     thread_local_ptr() = default;
      86                 :     ~thread_local_ptr() = default;
      87                 : 
      88                 :     thread_local_ptr(thread_local_ptr const&) = delete;
      89                 :     thread_local_ptr& operator=(thread_local_ptr const&) = delete;
      90                 : 
      91                 :     /** Return the pointer for this thread.
      92                 : 
      93                 :         @return The stored pointer, or nullptr if not set.
      94                 :     */
      95 HIT      687505 :     T* get() const noexcept
      96                 :     {
      97          687505 :         return ptr_;
      98                 :     }
      99                 : 
     100                 :     /** Set the pointer for this thread.
     101                 : 
     102                 :         @param p The pointer to store. The user manages its lifetime.
     103                 :     */
     104           36801 :     void set(T* p) noexcept
     105                 :     {
     106           36801 :         ptr_ = p;
     107           36801 :     }
     108                 : 
     109                 :     /** Dereference the stored pointer.
     110                 : 
     111                 :         @pre get() != nullptr
     112                 :     */
     113                 :     T& operator*() const noexcept
     114                 :     {
     115                 :         return *ptr_;
     116                 :     }
     117                 : 
     118                 :     /** Member access through the stored pointer.
     119                 : 
     120                 :         @pre get() != nullptr
     121                 :     */
     122                 :     T* operator->() const noexcept
     123                 :         requires std::is_class_v<T>
     124                 :     {
     125                 :         return ptr_;
     126                 :     }
     127                 : 
     128                 :     /** Assign a pointer value.
     129                 : 
     130                 :         @param p The pointer to store.
     131                 :         @return The stored pointer.
     132                 :     */
     133                 :     // NOLINTNEXTLINE(misc-unconventional-assign-operator)
     134                 :     T* operator=(T* p) noexcept
     135                 :     {
     136                 :         ptr_ = p;
     137                 :         return p;
     138                 :     }
     139                 : };
     140                 : 
     141                 : template<class T>
     142                 : BOOST_COROSIO_TLS_KEYWORD T* thread_local_ptr<T>::ptr_ = nullptr;
     143                 : 
     144                 : 
     145                 : #else
     146                 : 
     147                 : // Use C++11 thread_local keyword (fallback)
     148                 : 
     149                 : template<class T>
     150                 : class thread_local_ptr
     151                 : {
     152                 :     static thread_local T* ptr_;
     153                 : 
     154                 : public:
     155                 :     thread_local_ptr() = default;
     156                 :     ~thread_local_ptr() = default;
     157                 : 
     158                 :     thread_local_ptr(thread_local_ptr const&) = delete;
     159                 :     thread_local_ptr& operator=(thread_local_ptr const&) = delete;
     160                 : 
     161                 :     T* get() const noexcept
     162                 :     {
     163                 :         return ptr_;
     164                 :     }
     165                 : 
     166                 :     void set(T* p) noexcept
     167                 :     {
     168                 :         ptr_ = p;
     169                 :     }
     170                 : 
     171                 :     T& operator*() const noexcept
     172                 :     {
     173                 :         return *ptr_;
     174                 :     }
     175                 : 
     176                 :     T* operator->() const noexcept
     177                 :         requires std::is_class_v<T>
     178                 :     {
     179                 :         return ptr_;
     180                 :     }
     181                 : 
     182                 :     // NOLINTNEXTLINE(misc-unconventional-assign-operator)
     183                 :     T* operator=(T* p) noexcept
     184                 :     {
     185                 :         ptr_ = p;
     186                 :         return p;
     187                 :     }
     188                 : };
     189                 : 
     190                 : template<class T>
     191                 : thread_local T* thread_local_ptr<T>::ptr_ = nullptr;
     192                 : 
     193                 : #endif
     194                 : 
     195                 : } // namespace boost::corosio::detail
     196                 : 
     197                 : #endif
        

Generated by: LCOV version 2.3