Sources Pipelines Documentation

Allocators  
bitmapped_block.ipp
1 // Copyright (c) 2016 Lukasz Laszko
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 #pragma once
6 
7 #include <boost/memory/alignment.hpp>
8 #include <boost/utils/literals.hpp>
9 
10 #include <cstring>
11 
12 
13 namespace boost { namespace memory {
14 
15 template <typename bitmapped_block_type>
16 inline bitmapped_block_helper<bitmapped_block_type>::bitmapped_block_helper(bitmapped_block_type& instance) noexcept
17  :
18  instance_(instance)
19 {
20 
21 }
22 
23 template <typename bitmapped_block_type>
24 inline auto& bitmapped_block_helper<bitmapped_block_type>::get_allocator() noexcept
25 {
26  return instance_.allocator_;
27 }
28 
29 template <typename bitmapped_block_type>
30 inline auto& bitmapped_block_helper<bitmapped_block_type>::get_bitmap() noexcept
31 {
32  return *instance_.bitmap_;
33 }
34 
35 //template <typename bitmapped_block_type>
36 //inline auto& bitmapped_block_helper::get_block() noexcept
37 //{
38 // return
39 //}
40 
41 template <typename bitmap_type>
42 inline bitmap_helper<bitmap_type>::bitmap_helper(bitmap_type& instance) noexcept
43  :
44  instance_(instance)
45 {
46 
47 }
48 
49 template <typename bitmap_type>
50 inline std::uint8_t& bitmap_helper<bitmap_type>::get_flag(std::size_t index)
51 {
52  return instance_.flags_[index];
53 }
54 
55 template <typename bitmap_type>
56 inline constexpr std::size_t bitmap_helper<bitmap_type>::flags_count() const noexcept
57 {
58  return sizeof(instance_.flags_);
59 }
60 
61 template <
62  typename allocator,
63  std::size_t min,
64  std::size_t max,
65  std::size_t capacity,
66  std::size_t alignment>
67 template <
68  std::size_t size>
69 inline void bitmapped_block<
70  allocator,
71  min,
72  max,
73  capacity,
74  alignment>::bitmap<size>::set(std::size_t index)
75 {
76  auto& flag = flags_[index / 8ul];
77  flag |= flag_mask(index % 8ul);
78 }
79 
80 template <
81  typename allocator,
82  std::size_t min,
83  std::size_t max,
84  std::size_t capacity,
85  std::size_t alignment>
86 template <
87  std::size_t size>
88 inline void bitmapped_block<
89  allocator,
90  min,
91  max,
92  capacity,
93  alignment>::bitmap<size>::reset(std::size_t index)
94 {
95  auto& flag = flags_[index / 8ul];
96  flag &= ~flag_mask(index % 8ul);
97 }
98 
99 template <
100  typename allocator,
101  std::size_t min,
102  std::size_t max,
103  std::size_t capacity,
104  std::size_t alignment>
105 template <
106  std::size_t size>
107 inline void bitmapped_block<
108  allocator,
109  min,
110  max,
111  capacity,
112  alignment>::bitmap<size>::reset_all()
113 {
114  std::memset(flags_, 0, size);
115 }
116 
117 template <
118  typename allocator,
119  std::size_t min,
120  std::size_t max,
121  std::size_t capacity,
122  std::size_t alignment>
123 template <
124  std::size_t size>
125 inline bool bitmapped_block<
126  allocator,
127  min,
128  max,
129  capacity,
130  alignment>::bitmap<size>::is_set(std::size_t index)
131 {
132  auto& flag = flags_[index / 8ul];
133  return (flag & flag_mask(index % 8ul)) != 0_ui8;
134 }
135 
136 template <
137  typename allocator,
138  std::size_t min,
139  std::size_t max,
140  std::size_t capacity,
141  std::size_t alignment>
142 template <
143  std::size_t size>
144 inline bool bitmapped_block<
145  allocator,
146  min,
147  max,
148  capacity,
149  alignment>::bitmap<size>::claim(std::size_t& index)
150 {
151  for (auto i = 0ul; i < size; i++)
152  {
153  auto& flag = flags_[i];
154  if ((flag & all_mask) != all_mask)
155  {
156  for (auto j = 0_ui8; j < 8_ui8; j++)
157  {
158  auto mask = flag_mask(j);
159  if ((flag & mask) == 0_ui8)
160  {
161  flag |= mask;
162 
163  index = i * 8ul + j;
164  return true;
165  }
166  }
167  }
168  }
169 
170  return false;
171 }
172 
173 template <
174  typename allocator,
175  std::size_t min,
176  std::size_t max,
177  std::size_t capacity,
178  std::size_t alignment>
179 inline memory_block bitmapped_block<
180  allocator,
181  min,
182  max,
183  capacity,
184  alignment>::allocate(std::size_t size)
185 {
186  if (size < min || max < size)
187  return null_block;
188 
189  if (allocated_block_ == nullptr)
190  {
191  auto allocation_size = sizeof(bitmap_type)
192  + aligned_max_size * capacity
193  + (alignment > NO_ALIGNMENT ? alignment : 0ul);
194  allocated_block_ = allocator_.allocate(allocation_size);
195 
196  bitmap_ = reinterpret_cast<bitmap_type*>(allocated_block_.address);
197  bitmap_->reset_all();
198  }
199 
200  std::size_t index;
201  if (bitmap_->claim(index) && index < capacity)
202  {
203  auto first_address = align_forward<alignment>(allocated_block_ + sizeof(bitmap_type));
204  auto claimed_address = first_address + aligned_max_size * index;
205 
206  return { claimed_address, aligned_max_size };
207  }
208  else
209  {
210  return null_block;
211  }
212 }
213 
214 template <
215  typename allocator,
216  std::size_t min,
217  std::size_t max,
218  std::size_t capacity,
219  std::size_t alignment>
220 inline void bitmapped_block<
221  allocator,
222  min,
223  max,
224  capacity,
225  alignment>::deallocate(memory_block& block)
226 {
227  if (owns(block))
228  {
229  auto first_address = align_forward<alignment>(allocated_block_ + sizeof(bitmap_type));
230  auto offset = block - first_address;
231  auto index = offset / aligned_max_size;
232 
233  bitmap_->reset(index);
234  block = null_block;
235  }
236 }
237 
238 template <
239  typename allocator,
240  std::size_t min,
241  std::size_t max,
242  std::size_t capacity,
243  std::size_t alignment>
244 inline bool bitmapped_block<
245  allocator,
246  min,
247  max,
248  capacity,
249  alignment>::owns(memory_block& block)
250 {
251  if (allocated_block_ == nullptr)
252  return false;
253 
254  auto start_address = align_forward<alignment>(allocated_block_ + sizeof(bitmap_type));
255  if (block < start_address)
256  return false;
257 
258  auto allocation_size = sizeof(bitmap_type)
259  + aligned_max_size * capacity
260  + alignment;
261  auto end_address = allocated_block_ + allocation_size;
262  if (end_address < block)
263  return false;
264 
265  auto offset = block - start_address;
266  return offset % aligned_max_size == 0ul;
267 }
268 
269 } }
270