97.10% Lines (67/69) 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   164 monotonic_resource::
31   max_size() 31   max_size()
32   { 32   {
HITCBC 33   164 return std::size_t(-1) - sizeof(block); 33   164 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   39 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   39 if(n & (n - 1))
HITCBC 43   7 return next_pow2(n); 43   7 return next_pow2(n);
HITCBC 44   32 return n; 44   32 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   51 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   51 std::size_t result = min_size_;
HITCBC 54   213 while(result <= n) 54   213 while(result <= n)
55   { 55   {
HITCBC 56   163 if(result >= max_size() - result) 56   163 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   162 result *= 2;
63   } 63   }
HITCBC 64   51 return result; 64   51 return result;
65   } 65   }
66   66  
67   //---------------------------------------------------------- 67   //----------------------------------------------------------
68   68  
HITCBC 69   47 monotonic_resource:: 69   47 monotonic_resource::
HITCBC 70   47 ~monotonic_resource() 70   47 ~monotonic_resource()
71   { 71   {
HITCBC 72   47 release(); 72   47 release();
HITCBC 73   47 } 73   47 }
74   74  
HITCBC 75   37 monotonic_resource:: 75   37 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   37 storage_ptr upstream) noexcept
HITCBC 79   37 : buffer_{ 79   37 : buffer_{
80   nullptr, 0, 0, nullptr} 80   nullptr, 0, 0, nullptr}
HITCBC 81   74 , next_size_(round_pow2(initial_size)) 81   74 , next_size_(round_pow2(initial_size))
HITCBC 82   37 , upstream_(std::move(upstream)) 82   37 , upstream_(std::move(upstream))
83   { 83   {
HITCBC 84   37 } 84   37 }
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   48 monotonic_resource::
100   release() noexcept 100   release() noexcept
101   { 101   {
HITCBC 102   48 auto p = head_; 102   48 auto p = head_;
HITCBC 103   82 while(p != &buffer_) 103   82 while(p != &buffer_)
104   { 104   {
HITCBC 105   34 auto next = p->next; 105   34 auto next = p->next;
HITCBC 106   34 upstream_->deallocate(p, p->size); 106   34 upstream_->deallocate(p, p->size);
HITCBC 107   34 p = next; 107   34 p = next;
108   } 108   }
HITCBC 109   48 buffer_.p = reinterpret_cast< 109   48 buffer_.p = reinterpret_cast<
HITCBC 110   48 unsigned char*>(buffer_.p) - ( 110   48 unsigned char*>(buffer_.p) - (
HITCBC 111   48 buffer_.size - buffer_.avail); 111   48 buffer_.size - buffer_.avail);
HITCBC 112   48 buffer_.avail = buffer_.size; 112   48 buffer_.avail = buffer_.size;
HITCBC 113   48 head_ = &buffer_; 113   48 head_ = &buffer_;
HITCBC 114   48 } 114   48 }
115   115  
116   void* 116   void*
HITCBC 117   129498 monotonic_resource:: 117   129498 monotonic_resource::
118   do_allocate( 118   do_allocate(
119   std::size_t n, 119   std::size_t n,
120   std::size_t align) 120   std::size_t align)
121   { 121   {
HITCBC 122   129498 auto p = std::align(align, n, head_->p, head_->avail); 122   129498 auto p = std::align(align, n, head_->p, head_->avail);
HITCBC 123   129498 if(p) 123   129498 if(p)
124   { 124   {
HITCBC 125   129464 head_->p = reinterpret_cast< 125   129464 head_->p = reinterpret_cast<
HITCBC 126   129464 unsigned char*>(p) + n; 126   129464 unsigned char*>(p) + n;
HITCBC 127   129464 head_->avail -= n; 127   129464 head_->avail -= n;
HITCBC 128   129464 return p; 128   129464 return p;
129   } 129   }
130   130  
HITCBC 131   34 if(next_size_ < n) 131   34 if(next_size_ < n)
HITCBC 132   2 next_size_ = round_pow2(n); 132   2 next_size_ = round_pow2(n);
HITCBC 133   34 auto b = ::new(upstream_->allocate( 133   34 auto b = ::new(upstream_->allocate(
HITCBC 134   34 sizeof(block) + next_size_)) block; 134   34 sizeof(block) + next_size_)) block;
HITCBC 135   34 b->p = b + 1; 135   34 b->p = b + 1;
HITCBC 136   34 b->avail = next_size_; 136   34 b->avail = next_size_;
HITCBC 137   34 b->size = next_size_; 137   34 b->size = next_size_;
HITCBC 138   34 b->next = head_; 138   34 b->next = head_;
HITCBC 139   34 head_ = b; 139   34 head_ = b;
HITCBC 140   34 next_size_ = next_pow2(next_size_); 140   34 next_size_ = next_pow2(next_size_);
141   141  
HITCBC 142   34 p = std::align(align, n, head_->p, head_->avail); 142   34 p = std::align(align, n, head_->p, head_->avail);
HITCBC 143   34 BOOST_ASSERT(p); 143   34 BOOST_ASSERT(p);
HITCBC 144   34 head_->p = reinterpret_cast< 144   34 head_->p = reinterpret_cast<
HITCBC 145   34 unsigned char*>(p) + n; 145   34 unsigned char*>(p) + n;
HITCBC 146   34 head_->avail -= n; 146   34 head_->avail -= n;
HITCBC 147   34 return p; 147   34 return p;
148   } 148   }
149   149  
150   void 150   void
HITCBC 151   29 monotonic_resource:: 151   29 monotonic_resource::
152   do_deallocate( 152   do_deallocate(
153   void*, 153   void*,
154   std::size_t, 154   std::size_t,
155   std::size_t) 155   std::size_t)
156   { 156   {
157   // do nothing 157   // do nothing
HITCBC 158   29 } 158   29 }
159   159  
160   bool 160   bool
MISUBC 161   monotonic_resource:: 161   monotonic_resource::
162   do_is_equal( 162   do_is_equal(
163   memory_resource const& mr) const noexcept 163   memory_resource const& mr) const noexcept
164   { 164   {
MISUBC 165   return this == &mr; 165   return this == &mr;
166   } 166   }
167   167  
168   } // namespace json 168   } // namespace json
169   } // namespace boost 169   } // namespace boost
170   170  
171   #endif 171   #endif