97.14% Lines (68/70) 90.00% Functions (9/10)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3   // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com) 3   // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 5   // Distributed under the Boost Software License, Version 1.0. (See accompanying
6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/boostorg/json 8   // Official repository: https://github.com/boostorg/json
9   // 9   //
10   10  
11   #ifndef BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP 11   #ifndef BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
12   #define BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP 12   #define BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
13   13  
14   #include <boost/json/monotonic_resource.hpp> 14   #include <boost/json/monotonic_resource.hpp>
15   #include <boost/json/detail/except.hpp> 15   #include <boost/json/detail/except.hpp>
16   #include <boost/core/max_align.hpp> 16   #include <boost/core/max_align.hpp>
17   17  
18   #include <memory> 18   #include <memory>
19   19  
20   namespace boost { 20   namespace boost {
21   namespace json { 21   namespace json {
22   22  
23   struct alignas(core::max_align_t) 23   struct alignas(core::max_align_t)
24   monotonic_resource::block : block_base 24   monotonic_resource::block : block_base
25   { 25   {
26   }; 26   };
27   27  
28   constexpr 28   constexpr
29   std::size_t 29   std::size_t
HITCBC 30   164 monotonic_resource:: 30   179 monotonic_resource::
31   max_size() 31   max_size()
32   { 32   {
HITCBC 33   164 return std::size_t(-1) - sizeof(block); 33   179 return std::size_t(-1) - sizeof(block);
34   } 34   }
35   35  
36   // lowest power of 2 greater than or equal to n 36   // lowest power of 2 greater than or equal to n
37   std::size_t 37   std::size_t
HITCBC 38   39 monotonic_resource:: 38   42 monotonic_resource::
39   round_pow2( 39   round_pow2(
40   std::size_t n) noexcept 40   std::size_t n) noexcept
41   { 41   {
HITCBC 42   39 if(n & (n - 1)) 42   42 if(n & (n - 1))
HITCBC 43   7 return next_pow2(n); 43   8 return next_pow2(n);
HITCBC 44   32 return n; 44   34 return n;
45   } 45   }
46   46  
47   // lowest power of 2 greater than n 47   // lowest power of 2 greater than n
48   std::size_t 48   std::size_t
HITCBC 49   51 monotonic_resource:: 49   56 monotonic_resource::
50   next_pow2( 50   next_pow2(
51   std::size_t n) noexcept 51   std::size_t n) noexcept
52   { 52   {
HITCBC 53   51 std::size_t result = min_size_; 53   56 std::size_t result = min_size_;
HITCBC 54   213 while(result <= n) 54   233 while(result <= n)
55   { 55   {
HITCBC 56   163 if(result >= max_size() - result) 56   178 if(result >= max_size() - result)
57   { 57   {
58   // overflow 58   // overflow
HITCBC 59   1 result = max_size(); 59   1 result = max_size();
HITCBC 60   1 break; 60   1 break;
61   } 61   }
HITCBC 62   162 result *= 2; 62   177 result *= 2;
63   } 63   }
HITCBC 64   51 return result; 64   56 return result;
65   } 65   }
66   66  
67   //---------------------------------------------------------- 67   //----------------------------------------------------------
68   68  
HITCBC 69   47 monotonic_resource:: 69   49 monotonic_resource::
HITCBC 70   47 ~monotonic_resource() 70   49 ~monotonic_resource()
71   { 71   {
HITCBC 72   47 release(); 72   49 release();
HITCBC 73   47 } 73   49 }
74   74  
HITCBC 75   37 monotonic_resource:: 75   39 monotonic_resource::
76   monotonic_resource( 76   monotonic_resource(
77   std::size_t initial_size, 77   std::size_t initial_size,
HITCBC 78   37 storage_ptr upstream) noexcept 78   39 storage_ptr upstream) noexcept
HITCBC 79   37 : buffer_{ 79   39 : buffer_{
80   nullptr, 0, 0, nullptr} 80   nullptr, 0, 0, nullptr}
HITCBC 81   74 , next_size_(round_pow2(initial_size)) 81   78 , next_size_(round_pow2(initial_size))
HITCBC 82   37 , upstream_(std::move(upstream)) 82   39 , upstream_(std::move(upstream))
83   { 83   {
HITCBC 84   37 } 84   39 }
85   85  
HITCBC 86   10 monotonic_resource:: 86   10 monotonic_resource::
87   monotonic_resource( 87   monotonic_resource(
88   unsigned char* buffer, 88   unsigned char* buffer,
89   std::size_t size, 89   std::size_t size,
HITCBC 90   10 storage_ptr upstream) noexcept 90   10 storage_ptr upstream) noexcept
HITCBC 91   10 : buffer_{ 91   10 : buffer_{
92   buffer, size, size, nullptr} 92   buffer, size, size, nullptr}
HITCBC 93   20 , next_size_(next_pow2(size)) 93   20 , next_size_(next_pow2(size))
HITCBC 94   10 , upstream_(std::move(upstream)) 94   10 , upstream_(std::move(upstream))
95   { 95   {
HITCBC 96   10 } 96   10 }
97   97  
98   void 98   void
HITCBC 99   48 monotonic_resource:: 99   50 monotonic_resource::
100   release() noexcept 100   release() noexcept
101   { 101   {
HITCBC 102   48 auto p = head_; 102   50 auto p = head_;
HITCBC 103   82 while(p != &buffer_) 103   88 while(p != &buffer_)
104   { 104   {
HITCBC 105   34 auto next = p->next; 105   38 auto next = p->next;
HITCBC 106 - 34 upstream_->deallocate(p, p->size); 106 + 38 upstream_->deallocate(p,
HITGNC   107 + 38 sizeof(block) + p->size);
HITCBC 107   34 p = next; 108   38 p = next;
108   } 109   }
HITCBC 109   48 buffer_.p = reinterpret_cast< 110   50 buffer_.p = reinterpret_cast<
HITCBC 110   48 unsigned char*>(buffer_.p) - ( 111   50 unsigned char*>(buffer_.p) - (
HITCBC 111   48 buffer_.size - buffer_.avail); 112   50 buffer_.size - buffer_.avail);
HITCBC 112   48 buffer_.avail = buffer_.size; 113   50 buffer_.avail = buffer_.size;
HITCBC 113   48 head_ = &buffer_; 114   50 head_ = &buffer_;
HITCBC 114   48 } 115   50 }
115   116  
116   void* 117   void*
HITCBC 117   129498 monotonic_resource:: 118   129502 monotonic_resource::
118   do_allocate( 119   do_allocate(
119   std::size_t n, 120   std::size_t n,
120   std::size_t align) 121   std::size_t align)
121   { 122   {
HITCBC 122   129498 auto p = std::align(align, n, head_->p, head_->avail); 123   129502 auto p = std::align(align, n, head_->p, head_->avail);
HITCBC 123   129498 if(p) 124   129502 if(p)
124   { 125   {
HITCBC 125   129464 head_->p = reinterpret_cast< 126   129464 head_->p = reinterpret_cast<
HITCBC 126   129464 unsigned char*>(p) + n; 127   129464 unsigned char*>(p) + n;
HITCBC 127   129464 head_->avail -= n; 128   129464 head_->avail -= n;
HITCBC 128   129464 return p; 129   129464 return p;
129   } 130   }
130   131  
HITCBC 131   34 if(next_size_ < n) 132   38 if(next_size_ < n)
HITCBC 132   2 next_size_ = round_pow2(n); 133   3 next_size_ = round_pow2(n);
HITCBC 133   34 auto b = ::new(upstream_->allocate( 134   38 auto b = ::new(upstream_->allocate(
HITCBC 134   34 sizeof(block) + next_size_)) block; 135   38 sizeof(block) + next_size_)) block;
HITCBC 135   34 b->p = b + 1; 136   38 b->p = b + 1;
HITCBC 136   34 b->avail = next_size_; 137   38 b->avail = next_size_;
HITCBC 137   34 b->size = next_size_; 138   38 b->size = next_size_;
HITCBC 138   34 b->next = head_; 139   38 b->next = head_;
HITCBC 139   34 head_ = b; 140   38 head_ = b;
HITCBC 140   34 next_size_ = next_pow2(next_size_); 141   38 next_size_ = next_pow2(next_size_);
141   142  
HITCBC 142   34 p = std::align(align, n, head_->p, head_->avail); 143   38 p = std::align(align, n, head_->p, head_->avail);
HITCBC 143   34 BOOST_ASSERT(p); 144   38 BOOST_ASSERT(p);
HITCBC 144   34 head_->p = reinterpret_cast< 145   38 head_->p = reinterpret_cast<
HITCBC 145   34 unsigned char*>(p) + n; 146   38 unsigned char*>(p) + n;
HITCBC 146   34 head_->avail -= n; 147   38 head_->avail -= n;
HITCBC 147   34 return p; 148   38 return p;
148   } 149   }
149   150  
150   void 151   void
HITCBC 151   29 monotonic_resource:: 152   29 monotonic_resource::
152   do_deallocate( 153   do_deallocate(
153   void*, 154   void*,
154   std::size_t, 155   std::size_t,
155   std::size_t) 156   std::size_t)
156   { 157   {
157   // do nothing 158   // do nothing
HITCBC 158   29 } 159   29 }
159   160  
160   bool 161   bool
MISUBC 161   monotonic_resource:: 162   monotonic_resource::
162   do_is_equal( 163   do_is_equal(
163   memory_resource const& mr) const noexcept 164   memory_resource const& mr) const noexcept
164   { 165   {
MISUBC 165   return this == &mr; 166   return this == &mr;
166   } 167   }
167   168  
168   } // namespace json 169   } // namespace json
169   } // namespace boost 170   } // namespace boost
170   171  
171   #endif 172   #endif