HeterogenousContinuousContainer.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotAPI::RobotUnit
17 * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18 * @date 2018
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#pragma once
24
25#include <vector>
26
30
32
33#if __GNUC__ < 5 && !defined(__clang__)
34namespace std
35{
36 inline void*
37 align(size_t alignment, size_t bytes, void*& bufferPlace, size_t& bufferSpace) noexcept
38 {
39 const auto uiptr = reinterpret_cast<uintptr_t>(bufferPlace);
40 const auto alignedPlace = (uiptr - 1u + alignment) & -alignment;
41 const auto spaceRequired = alignedPlace - uiptr;
42 if ((bytes + spaceRequired) > bufferSpace)
43 {
44 return nullptr;
45 }
46 else
47 {
48 bufferSpace -= spaceRequired;
49 return bufferPlace = reinterpret_cast<void*>(alignedPlace);
50 }
51 }
52} // namespace std
53#endif
54
55namespace armarx::detail
56{
57 template <class Base>
59 {
60 public:
61 bool
62 empty() const
63 {
64 return begin_ == current_;
65 }
66
67 bool
68 owning() const
69 {
70 return storage_ != nullptr;
71 }
72
73 std::size_t
75 {
76 return static_cast<const std::uint8_t*>(end_) -
77 static_cast<const std::uint8_t*>(current_);
78 }
79
80 std::size_t
82 {
83 return static_cast<const std::uint8_t*>(end_) -
84 static_cast<const std::uint8_t*>(begin_);
85 }
86
87 std::size_t
89 {
90 return static_cast<const std::uint8_t*>(current_) -
91 static_cast<const std::uint8_t*>(begin_);
92 }
93
94 void
95 assignStorage(void* begin, void* end)
96 {
98 ARMARX_CHECK_LESS_EQUAL(begin, end);
99 storage_ = nullptr;
100 begin_ = begin;
101 current_ = begin;
102 end_ = end;
103 }
104
105 void
106 setStorageCapacity(std::size_t sz)
107 {
109 if (!sz)
110 {
111 assignStorage(nullptr, nullptr);
112 return;
113 }
114 //replache with void* aligned_alloc( std::size_t alignment, std::size_t size ) @c++17
115 sz += 63;
116 storage_.reset(new std::uint8_t[sz]);
117 begin_ = static_cast<void*>(storage_.get());
118 current_ = begin_;
119 end_ = static_cast<void*>(storage_.get() + sz);
120 }
121
122 protected:
123 template <class Derived>
124 Base*
125 pushBack(const Derived* d)
126 {
127 static_assert(
128 std::is_base_of<Base, Derived>::value,
129 "HeterogenousContinuousContainerBase::pushBack: Derived must derive Base");
130 std::size_t space_ = getRemainingStorageCapacity();
131
132 void* ptr = std::align(d->_alignof(), d->_sizeof(), current_, space_);
133
134 if (!ptr)
135 {
136 return nullptr;
137 }
138 current_ = static_cast<void*>(static_cast<std::uint8_t*>(ptr) + d->_sizeof());
139 return d->_placementCopyConstruct(ptr);
140 }
141
142 void
144 {
145 current_ = begin_;
146 }
147
148 private:
149 std::unique_ptr<std::uint8_t[]> storage_{nullptr};
150 void* begin_{nullptr};
151 void* current_{nullptr};
152 void* end_{nullptr};
153 };
154} // namespace armarx::detail
155
156namespace armarx
157{
158 template <class Base, bool UsePropagateConst = true>
160 {
162
163 public:
165 typename std::conditional<UsePropagateConst, PropagateConst<Base*>, Base*>::type;
166
169
171 bool compressElems = false)
172 {
173 this->setStorageCapacity(compressElems ? other.getUsedStorageCapacity()
174 : other.getStorageCapacity());
175 setElementCapacity(compressElems ? other.elements().size()
176 : other.elements().capacity());
177 for (auto& e : other.elements())
178 {
179 pushBack(e);
180 }
181 }
182
184
187 {
188 clear();
190 setElementCapacity(other.elements().capacity());
191 for (auto& e : other.elements())
192 {
193 pushBack(e);
194 }
195 return *this;
196 }
197
202
203 std::size_t
205 {
206 return elements_.size();
207 }
208
209 std::size_t
211 {
212 return elements_.capacity();
213 }
214
215 std::size_t
220
221 void
222 setElementCapacity(std::size_t cnt)
223 {
225 if (elements_.capacity() > cnt)
226 {
227 //force the capacity to reduce
228 elements_ = std::vector<ElementType>{};
229 }
230 elements_.reserve(cnt);
231 }
232
233 template <class Derived>
234 Base*
235 pushBack(const Derived* d)
236 {
237 static_assert(
238 std::is_base_of<Base, Derived>::value,
239 "HeterogenousContinuousContainerBase::pushBack: Derived must derive Base");
242 {
243 return nullptr;
244 }
245 Base* const ptr = BaseContainer::pushBack(d);
246 if (ptr)
247 {
248 elements_.emplace_back(ptr);
249 }
250 return ptr;
251 }
252
253 template <class Derived>
254 Base*
256 {
257 return pushBack(*d);
258 }
259
260 template <class Derived>
261 Base*
262 pushBack(const Derived& d)
263 {
264 return pushBack(&d);
265 }
266
267 std::vector<ElementType>&
269 {
270 return elements_;
271 }
272
273 const std::vector<ElementType>&
274 elements() const
275 {
276 return elements_;
277 }
278
279 void
281 {
282 for (auto& e : elements_)
283 {
284 e->~Base();
285 }
286 elements_.clear();
288 }
289
290 private:
291 std::vector<ElementType> elements_;
292 };
293
294 template <class Base, bool UsePropagateConst = true>
297 {
299
300 public:
302 typename std::conditional<UsePropagateConst, PropagateConst<Base*>, Base*>::type;
303
306
308 bool compressElems = false)
309 {
310 setStorageCapacity(compressElems ? other.getUsedStorageCapacity()
311 : other.getStorageCapacity());
312 std::vector<std::size_t> elemCaps;
313 elemCaps.reserve(other.elements().size());
314 for (const auto& d1 : other.elements())
315 {
316 elemCaps.emplace_back(compressElems ? d1.size() : d1.capacity());
317 }
318 setElementCapacity(elemCaps);
319 for (std::size_t i = 0; i < other.elements().size(); ++i)
320 {
321 for (auto& e : other.elements().at(i))
322 {
323 pushBack(i, e);
324 }
325 }
326 }
327
329
332 {
333 clear();
335 std::vector<std::size_t> elemCaps;
336 elemCaps.reserve(other.elements().size());
337 for (const auto& d1 : other.elements())
338 {
339 elemCaps.emplace_back(d1.capacity());
340 }
341 setElementCapacity(elemCaps);
342 for (std::size_t i = 0; i < other.elements().size(); ++i)
343 {
344 for (auto& e : other.elements().at(i))
345 {
346 pushBack(i, e);
347 }
348 }
349 return *this;
350 }
351
356
357 std::size_t
358 getElementCount(std::size_t d0) const
359 {
360 return elements_.at(d0).size();
361 }
362
363 std::size_t
364 getElementCapacity(std::size_t d0) const
365 {
366 return elements_.at(d0).capacity();
367 }
368
369 std::size_t
370 getRemainingElementCapacity(std::size_t d0) const
371 {
372 return getElementCapacity(d0) - getElementCount(d0);
373 }
374
375 void
376 setElementCapacity(const std::vector<std::size_t>& cnt)
377 {
379 elements_.resize(cnt.size());
380 for (std::size_t i = 0; i < cnt.size(); ++i)
381 {
382 if (elements_.at(i).capacity() > cnt)
383 {
384 //force the capacity to reduce
385 elements_.at(i) = std::vector<ElementType>{};
386 }
387 elements_.at(i).reserve(cnt.at(i));
388 }
389 }
390
391 template <class Derived>
392 Base*
393 pushBack(std::size_t d0, const Derived* d)
394 {
395 static_assert(
396 std::is_base_of<Base, Derived>::value,
397 "HeterogenousContinuousContainerBase::pushBack: Derived must derive Base");
400 {
401 return nullptr;
402 }
403 Base* const ptr = BaseContainer::pushBack(d);
404 if (ptr)
405 {
406 elements_.at(d0).emplace_back(ptr);
407 }
408 return ptr;
409 }
410
411 template <class Derived>
412 Base*
413 pushBack(std::size_t d0, const PropagateConst<Derived*>& d)
414 {
415 return pushBack(d0, *d);
416 }
417
418 template <class Derived>
419 Base*
420 pushBack(std::size_t d0, const Derived& d)
421 {
422 return pushBack(d0, &d);
423 }
424
425 std::vector<std::vector<ElementType>>&
427 {
428 return elements_;
429 }
430
431 const std::vector<std::vector<ElementType>>&
432 elements() const
433 {
434 return elements_;
435 }
436
437 void
439 {
440 for (auto& d1 : elements_)
441 {
442 for (auto& e : d1)
443 {
444 e->~Base();
445 }
446 d1.clear();
447 }
449 }
450
451 private:
452 std::vector<std::vector<ElementType>> elements_;
453 };
454} // namespace armarx
std::size_t getRemainingElementCapacity(std::size_t d0) const
HeterogenousContinuous2DContainer & operator=(const HeterogenousContinuous2DContainer &other)
typename std::conditional< UsePropagateConst, PropagateConst< Base * >, Base * >::type ElementType
std::vector< std::vector< ElementType > > & elements()
void setElementCapacity(const std::vector< std::size_t > &cnt)
HeterogenousContinuous2DContainer(HeterogenousContinuous2DContainer &&)=default
Base * pushBack(std::size_t d0, const Derived &d)
HeterogenousContinuous2DContainer(const HeterogenousContinuous2DContainer &other, bool compressElems=false)
Base * pushBack(std::size_t d0, const Derived *d)
const std::vector< std::vector< ElementType > > & elements() const
HeterogenousContinuous2DContainer & operator=(HeterogenousContinuous2DContainer &&)=default
Base * pushBack(std::size_t d0, const PropagateConst< Derived * > &d)
HeterogenousContinuousContainer & operator=(const HeterogenousContinuousContainer &other)
typename std::conditional< UsePropagateConst, PropagateConst< Base * >, Base * >::type ElementType
HeterogenousContinuousContainer(const HeterogenousContinuousContainer &other, bool compressElems=false)
HeterogenousContinuousContainer(HeterogenousContinuousContainer &&)=default
Base * pushBack(const PropagateConst< Derived * > &d)
HeterogenousContinuousContainer & operator=(HeterogenousContinuousContainer &&)=default
const std::vector< ElementType > & elements() const
Wrapper for a pointer to propagate const to the pointed to value.
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_LESS_EQUAL(lhs, rhs)
This macro evaluates whether lhs is less or equal (<=) rhs and if it turns out to be false it will th...
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
This file offers overloads of toIce() and fromIce() functions for STL container types.
void * align(size_t alignment, size_t bytes, void *&bufferPlace, size_t &bufferSpace) noexcept