aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/almalloc.h78
1 files changed, 73 insertions, 5 deletions
diff --git a/common/almalloc.h b/common/almalloc.h
index 0d77c46d..74aa4afe 100644
--- a/common/almalloc.h
+++ b/common/almalloc.h
@@ -39,6 +39,8 @@ int al_is_sane_alignment_allocator(void) noexcept;
namespace al {
+#define REQUIRES(...) typename std::enable_if<(__VA_ARGS__),int>::type = 0
+
template<typename T, size_t alignment=alignof(T)>
struct allocator : public std::allocator<T> {
using size_type = size_t;
@@ -85,6 +87,73 @@ inline T* assume_aligned(T *ptr) noexcept
#endif
}
+template<typename T>
+inline void destroy_at(T *ptr) { ptr->~T(); }
+
+template<typename T>
+inline void destroy(T first, const T end)
+{
+ while(first != end)
+ {
+ destroy_at(std::addressof(*first));
+ ++first;
+ }
+}
+
+template<typename T, typename N, REQUIRES(std::is_integral<N>::value)>
+inline T destroy_n(T first, N count)
+{
+ if(count != 0)
+ {
+ do {
+ destroy_at(std::addressof(*first));
+ ++first;
+ } while(--count);
+ }
+ return first;
+}
+
+
+template<typename T>
+inline void uninitialized_default_construct(T first, const T last)
+{
+ using ValueT = typename std::iterator_traits<T>::value_type;
+ T current{first};
+ try {
+ while(current != last)
+ {
+ ::new (static_cast<void*>(std::addressof(*current))) ValueT;
+ ++current;
+ }
+ }
+ catch(...) {
+ destroy(first, current);
+ throw;
+ }
+}
+
+template<typename T, typename N, REQUIRES(std::is_integral<N>::value)>
+inline T uninitialized_default_construct_n(T first, N count)
+{
+ using ValueT = typename std::iterator_traits<T>::value_type;
+ T current{first};
+ if(count != 0)
+ {
+ try {
+ do {
+ ::new (static_cast<void*>(std::addressof(*current))) ValueT;
+ ++current;
+ } while(--count);
+ }
+ catch(...) {
+ destroy(first, current);
+ throw;
+ }
+ }
+ return current;
+}
+
+
/* std::make_unique was added with C++14, so until we rely on that, make our
* own version.
*/
@@ -109,12 +178,9 @@ struct FlexArray {
}
FlexArray(size_t size) : mSize{size}
- { new (mArray) T[mSize]; }
+ { uninitialized_default_construct_n(mArray, mSize); }
~FlexArray()
- {
- for(size_t i{0u};i < mSize;++i)
- mArray[i].~T();
- }
+ { destroy_n(mArray, mSize); }
FlexArray(const FlexArray&) = delete;
FlexArray& operator=(const FlexArray&) = delete;
@@ -143,6 +209,8 @@ struct FlexArray {
DEF_PLACE_NEWDEL()
};
+#undef REQUIRES
+
} // namespace al
#endif /* AL_MALLOC_H */