90.91% Lines (70/77) 100.00% Functions (13/13)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/boostorg/url 7   // Official repository: https://github.com/boostorg/url
8   // 8   //
9   9  
10   #ifndef BOOST_URL_GRAMMAR_IMPL_RECYCLED_PTR_HPP 10   #ifndef BOOST_URL_GRAMMAR_IMPL_RECYCLED_PTR_HPP
11   #define BOOST_URL_GRAMMAR_IMPL_RECYCLED_PTR_HPP 11   #define BOOST_URL_GRAMMAR_IMPL_RECYCLED_PTR_HPP
12   12  
13   #include <boost/assert.hpp> 13   #include <boost/assert.hpp>
14   14  
15   namespace boost { 15   namespace boost {
16   namespace urls { 16   namespace urls {
17   namespace grammar { 17   namespace grammar {
18   18  
19   //------------------------------------------------ 19   //------------------------------------------------
20   20  
21   template<class T> 21   template<class T>
HITCBC 22   5 recycled<T>:: 22   5 recycled<T>::
23   ~recycled() 23   ~recycled()
24   { 24   {
HITCBC 25   5 std::size_t n = 0; 25   5 std::size_t n = 0;
26   // VFALCO we should probably deallocate 26   // VFALCO we should probably deallocate
27   // in reverse order of allocation but 27   // in reverse order of allocation but
28   // that requires a doubly-linked list. 28   // that requires a doubly-linked list.
HITCBC 29   5 auto it = head_; 29   5 auto it = head_;
HITCBC 30   12 while(it) 30   12 while(it)
31   { 31   {
HITCBC 32   7 ++n; 32   7 ++n;
HITCBC 33   7 auto next = it->next; 33   7 auto next = it->next;
HITCBC 34   7 BOOST_ASSERT( 34   7 BOOST_ASSERT(
35   it->refs == 0); 35   it->refs == 0);
HITCBC 36   7 delete it; 36   7 delete it;
HITCBC 37   7 it = next; 37   7 it = next;
38   } 38   }
HITCBC 39   5 implementation_defined::recycled_remove( 39   5 implementation_defined::recycled_remove(
40   sizeof(U) * n); 40   sizeof(U) * n);
HITCBC 41   5 } 41   5 }
42   42  
43   template<class T> 43   template<class T>
44   auto 44   auto
HITCBC 45   18 recycled<T>:: 45   18 recycled<T>::
46   acquire() -> 46   acquire() ->
47   U* 47   U*
48   { 48   {
49   U* p; 49   U* p;
50   { 50   {
51   #if !defined(BOOST_URL_DISABLE_THREADS) 51   #if !defined(BOOST_URL_DISABLE_THREADS)
52   std::lock_guard< 52   std::lock_guard<
HITCBC 53   18 std::mutex> lock(m_); 53   18 std::mutex> lock(m_);
54   #endif 54   #endif
HITCBC 55   18 p = head_; 55   18 p = head_;
HITCBC 56   18 if(p) 56   18 if(p)
57   { 57   {
58   // reuse 58   // reuse
HITCBC 59   11 head_ = head_->next; 59   11 head_ = head_->next;
HITCBC 60   11 implementation_defined::recycled_remove( 60   11 implementation_defined::recycled_remove(
61   sizeof(U)); 61   sizeof(U));
HITCBC 62   11 ++p->refs; 62   11 ++p->refs;
63   } 63   }
64   else 64   else
65   { 65   {
HITCBC 66   7 p = new U; 66   7 p = new U;
67   } 67   }
HITCBC 68   18 } 68   18 }
HITCBC 69   18 BOOST_ASSERT(p->refs == 1); 69   18 BOOST_ASSERT(p->refs == 1);
HITCBC 70   18 return p; 70   18 return p;
71   } 71   }
72   72  
73   template<class T> 73   template<class T>
74   void 74   void
HITCBC 75   24 recycled<T>:: 75   24 recycled<T>::
76   release(U* u) noexcept 76   release(U* u) noexcept
77   { 77   {
HITCBC 78   24 if(--u->refs != 0) 78   24 if(--u->refs != 0)
HITCBC 79   6 return; 79   6 return;
80   { 80   {
81   #if !defined(BOOST_URL_DISABLE_THREADS) 81   #if !defined(BOOST_URL_DISABLE_THREADS)
82   std::lock_guard< 82   std::lock_guard<
HITCBC 83   18 std::mutex> lock(m_); 83   18 std::mutex> lock(m_);
84   #endif 84   #endif
HITCBC 85   18 u->next = head_; 85   18 u->next = head_;
HITCBC 86   18 head_ = u; 86   18 head_ = u;
HITCBC 87   18 } 87   18 }
HITCBC 88   18 implementation_defined::recycled_add( 88   18 implementation_defined::recycled_add(
89   sizeof(U)); 89   sizeof(U));
90   } 90   }
91   91  
92   //------------------------------------------------ 92   //------------------------------------------------
93   93  
94   template<class T> 94   template<class T>
HITCBC 95   52 recycled_ptr<T>:: 95   52 recycled_ptr<T>::
96   ~recycled_ptr() 96   ~recycled_ptr()
97   { 97   {
HITCBC 98   52 if(p_) 98   52 if(p_)
HITCBC 99   23 bin_->release(p_); 99   23 bin_->release(p_);
HITCBC 100   52 } 100   52 }
101   101  
102   template<class T> 102   template<class T>
HITCBC 103   1 recycled_ptr<T>:: 103   1 recycled_ptr<T>::
104   recycled_ptr( 104   recycled_ptr(
105   recycled<T>& bin) 105   recycled<T>& bin)
HITCBC 106   1 : bin_(&bin) 106   1 : bin_(&bin)
HITCBC 107   1 , p_(bin.acquire()) 107   1 , p_(bin.acquire())
108   { 108   {
HITCBC 109   1 } 109   1 }
110   110  
111   template<class T> 111   template<class T>
HITCBC 112   17 recycled_ptr<T>:: 112   17 recycled_ptr<T>::
113   recycled_ptr( 113   recycled_ptr(
114   recycled<T>& bin, 114   recycled<T>& bin,
115   std::nullptr_t) noexcept 115   std::nullptr_t) noexcept
HITCBC 116   17 : bin_(&bin) 116   17 : bin_(&bin)
117   { 117   {
HITCBC 118   17 } 118   17 }
119   119  
120   template<class T> 120   template<class T>
HITCBC 121   17 recycled_ptr<T>:: 121   17 recycled_ptr<T>::
122   recycled_ptr() 122   recycled_ptr()
HITCBC 123   17 : recycled_ptr(nullptr) 123   17 : recycled_ptr(nullptr)
124   { 124   {
HITCBC 125   17 p_ = bin_->acquire(); 125   17 p_ = bin_->acquire();
HITCBC 126   17 } 126   17 }
127   127  
128   template<class T> 128   template<class T>
HITCBC 129   17 recycled_ptr<T>:: 129   17 recycled_ptr<T>::
130   recycled_ptr( 130   recycled_ptr(
131   std::nullptr_t) noexcept 131   std::nullptr_t) noexcept
HITCBC 132   34 : recycled_ptr([]() -> B& 132   34 : recycled_ptr([]() -> B&
133   { 133   {
134   // VFALCO need guaranteed constexpr-init 134   // VFALCO need guaranteed constexpr-init
HITCBC 135   17 static B r; 135   17 static B r;
HITCBC 136   17 return r; 136   17 return r;
HITCBC 137   17 }(), nullptr) 137   17 }(), nullptr)
138   { 138   {
HITCBC 139   17 } 139   17 }
140   140  
141   template<class T> 141   template<class T>
HITCBC 142   6 recycled_ptr<T>:: 142   6 recycled_ptr<T>::
143   recycled_ptr( 143   recycled_ptr(
144   recycled_ptr const& other) noexcept 144   recycled_ptr const& other) noexcept
HITCBC 145   6 : bin_(other.bin_) 145   6 : bin_(other.bin_)
HITCBC 146   6 , p_(other.p_) 146   6 , p_(other.p_)
147   { 147   {
HITCBC 148   6 if(p_) 148   6 if(p_)
HITCBC 149   6 ++p_->refs; 149   6 ++p_->refs;
HITCBC 150   6 } 150   6 }
151   151  
152   template<class T> 152   template<class T>
HITCBC 153   28 recycled_ptr<T>:: 153   28 recycled_ptr<T>::
154   recycled_ptr( 154   recycled_ptr(
155   recycled_ptr&& other) noexcept 155   recycled_ptr&& other) noexcept
HITCBC 156   28 : bin_(other.bin_) 156   28 : bin_(other.bin_)
HITCBC 157   28 , p_(other.p_) 157   28 , p_(other.p_)
158   { 158   {
HITCBC 159   28 other.p_ = nullptr; 159   28 other.p_ = nullptr;
HITCBC 160   28 } 160   28 }
161   161  
162   template<class T> 162   template<class T>
163   auto 163   auto
164   recycled_ptr<T>:: 164   recycled_ptr<T>::
165   operator=( 165   operator=(
166   recycled_ptr&& other) noexcept -> 166   recycled_ptr&& other) noexcept ->
167   recycled_ptr& 167   recycled_ptr&
168   { 168   {
169   BOOST_ASSERT( 169   BOOST_ASSERT(
170   bin_ == other.bin_); 170   bin_ == other.bin_);
171   if(p_) 171   if(p_)
172   bin_->release(p_); 172   bin_->release(p_);
173   p_ = other.p_; 173   p_ = other.p_;
174   other.p_ = nullptr; 174   other.p_ = nullptr;
175   return *this; 175   return *this;
176   } 176   }
177   177  
178   template<class T> 178   template<class T>
179   auto 179   auto
HITCBC 180   1 recycled_ptr<T>:: 180   1 recycled_ptr<T>::
181   operator=( 181   operator=(
182   recycled_ptr const& other) noexcept -> 182   recycled_ptr const& other) noexcept ->
183   recycled_ptr& 183   recycled_ptr&
184   { 184   {
HITCBC 185   1 if(this == &other) 185   1 if(this == &other)
HITCBC 186   1 return *this; 186   1 return *this;
MISUBC 187   BOOST_ASSERT( 187   BOOST_ASSERT(
188   bin_ == other.bin_); 188   bin_ == other.bin_);
MISUBC 189   if(p_) 189   if(p_)
MISUBC 190   bin_->release(p_); 190   bin_->release(p_);
MISUBC 191   p_ = other.p_; 191   p_ = other.p_;
MISUBC 192   if(p_) 192   if(p_)
MISUBC 193   ++p_->refs; 193   ++p_->refs;
MISUBC 194   return *this; 194   return *this;
195   } 195   }
196   196  
197   template<class T> 197   template<class T>
198   T& 198   T&
199   recycled_ptr<T>:: 199   recycled_ptr<T>::
200   acquire() 200   acquire()
201   { 201   {
202   if(! p_) 202   if(! p_)
203   p_ = bin_->acquire(); 203   p_ = bin_->acquire();
204   return p_->t; 204   return p_->t;
205   } 205   }
206   206  
207   template<class T> 207   template<class T>
208   void 208   void
HITCBC 209   1 recycled_ptr<T>:: 209   1 recycled_ptr<T>::
210   release() noexcept 210   release() noexcept
211   { 211   {
HITCBC 212   1 if(p_) 212   1 if(p_)
213   { 213   {
HITCBC 214   1 bin_->release(p_); 214   1 bin_->release(p_);
HITCBC 215   1 p_ = nullptr; 215   1 p_ = nullptr;
216   } 216   }
HITCBC 217   1 } 217   1 }
218   218  
219   } // grammar 219   } // grammar
220   } // urls 220   } // urls
221   } // boost 221   } // boost
222   222  
223   #endif 223   #endif