summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/palloc.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/palloc.h')
-rw-r--r--src/lib/netlist/plib/palloc.h378
1 files changed, 211 insertions, 167 deletions
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h
index d7b00262f7f..f10fd548817 100644
--- a/src/lib/netlist/plib/palloc.h
+++ b/src/lib/netlist/plib/palloc.h
@@ -17,6 +17,7 @@
#include <memory>
#include <utility>
#include <vector>
+#include <type_traits>
#if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
#include <malloc.h>
@@ -25,127 +26,65 @@
namespace plib {
//============================================================
- // Memory allocation
+ // Standard arena_deleter
//============================================================
-#if (USE_ALIGNED_ALLOCATION)
- static inline void *paligned_alloc( size_t alignment, size_t size )
+ template <typename P, typename T>
+ struct arena_deleter
{
-#if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
- return _aligned_malloc(size, alignment);
-#elif defined(__APPLE__)
- void* p;
- if (::posix_memalign(&p, alignment, size) != 0) {
- p = nullptr;
+ //using arena_storage_type = P *;
+ using arena_storage_type = typename std::conditional<P::is_stateless, P, P *>::type;
+ template <typename X, typename Y = void>
+ typename std::enable_if<!X::is_stateless, X&>::type getref(X *x) { return *x;}
+ template <typename X, typename Y = void *>
+ typename std::enable_if<std::remove_pointer<X>::type::is_stateless, X&>::type
+ getref(X &x, Y y = nullptr)
+ {
+ unused_var(y);
+ return x;
}
- return p;
-#else
- return aligned_alloc(alignment, size);
-#endif
- }
-
- static inline void pfree( void *ptr )
- {
- // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
- free(ptr);
- }
-
-#else
- static inline void *paligned_alloc( size_t alignment, size_t size )
- {
- unused_var(alignment);
- return ::operator new(size);
- }
-
- static inline void pfree( void *ptr )
- {
- ::operator delete(ptr);
- }
-#endif
-
- template <typename T, std::size_t ALIGN>
- /*inline */ C14CONSTEXPR T *assume_aligned_ptr(T *p) noexcept
- {
- static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)");
- static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
- //auto t = reinterpret_cast<std::uintptr_t>(p);
- //if (t & (ALIGN-1))
- // printf("alignment error!");
-#if (USE_ALIGNED_HINTS)
- return reinterpret_cast<T *>(__builtin_assume_aligned(p, ALIGN));
-#else
- return p;
-#endif
- }
-
- template <typename T, std::size_t ALIGN>
- constexpr const T *assume_aligned_ptr(const T *p) noexcept
- {
- static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)");
- static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
-#if (USE_ALIGNED_HINTS)
- return reinterpret_cast<const T *>(__builtin_assume_aligned(p, ALIGN));
-#else
- return p;
-#endif
- }
-
- template<typename T, typename... Args>
- inline T *pnew(Args&&... args)
- {
- auto *p = paligned_alloc(alignof(T), sizeof(T));
- return new(p) T(std::forward<Args>(args)...);
- }
- template<typename T>
- inline void pdelete(T *ptr)
- {
- ptr->~T();
- pfree(ptr);
- }
+ constexpr arena_deleter(arena_storage_type a = arena_storage_type()) noexcept
+ : m_a(a) { }
- template<typename T>
- inline T* pnew_array(const std::size_t num)
- {
- return new T[num]();
- }
-
- template<typename T>
- inline void pdelete_array(T *ptr)
- {
- delete [] ptr;
- }
-
- template <typename T>
- struct pdefault_deleter
- {
- constexpr pdefault_deleter() noexcept = default;
-
- template<typename U, typename = typename
+ template<typename PU, typename U, typename = typename
std::enable_if<std::is_convertible< U*, T*>::value>::type>
- pdefault_deleter(const pdefault_deleter<U>&) noexcept { }
+ arena_deleter(const arena_deleter<PU, U> &rhs) noexcept : m_a(rhs.m_a) { }
- void operator()(T *p) const
+ void operator()(T *p) //const
{
- pdelete(p);
+ /* call destructor */
+ p->~T();
+ getref(m_a).deallocate(p);
}
+ //private:
+ arena_storage_type m_a;
};
- template <typename SC, typename D = pdefault_deleter<SC>>
+ //============================================================
+ // owned_ptr: smart pointer with ownership information
+ //============================================================
+
+ template <typename SC, typename D>
class owned_ptr
{
public:
+
+ using pointer = SC *;
+ using element_type = SC;
+ using deleter_type = D;
+
owned_ptr()
- : m_ptr(nullptr), m_is_owned(true) { }
+ : m_ptr(nullptr), m_deleter(), m_is_owned(true) { }
template <typename, typename>
friend class owned_ptr;
- owned_ptr(SC *p, bool owned) noexcept
+ owned_ptr(pointer p, bool owned) noexcept
: m_ptr(p), m_deleter(), m_is_owned(owned)
{ }
- owned_ptr(SC *p, bool owned, D deleter) noexcept
+ owned_ptr(pointer p, bool owned, D deleter) noexcept
: m_ptr(p), m_deleter(deleter), m_is_owned(owned)
{ }
@@ -168,10 +107,10 @@ namespace plib {
}
owned_ptr(owned_ptr &&r) noexcept
+ : m_ptr(r.m_ptr)
+ , m_deleter(r.m_deleter)
+ , m_is_owned(r.m_is_owned)
{
- m_is_owned = r.m_is_owned;
- m_ptr = r.m_ptr;
- m_deleter = r.m_deleter;
r.m_is_owned = false;
r.m_ptr = nullptr;
}
@@ -183,7 +122,7 @@ namespace plib {
m_deleter(m_ptr);
m_is_owned = r.m_is_owned;
m_ptr = r.m_ptr;
- m_deleter = r.m_deleter;
+ m_deleter = std::move(r.m_deleter);
r.m_is_owned = false;
r.m_ptr = nullptr;
return *this;
@@ -191,10 +130,10 @@ namespace plib {
template<typename DC, typename DC_D>
owned_ptr(owned_ptr<DC, DC_D> &&r) noexcept
+ : m_ptr(static_cast<pointer >(r.get()))
+ , m_deleter(r.m_deleter)
+ , m_is_owned(r.is_owned())
{
- m_ptr = static_cast<SC *>(r.get());
- m_is_owned = r.is_owned();
- m_deleter = r.m_deleter;
r.release();
}
@@ -208,9 +147,9 @@ namespace plib {
m_is_owned = false;
m_ptr = nullptr;
}
- SC * release()
+ pointer release()
{
- SC *tmp = m_ptr;
+ pointer tmp = m_ptr;
m_is_owned = false;
m_ptr = nullptr;
return tmp;
@@ -218,98 +157,217 @@ namespace plib {
bool is_owned() const { return m_is_owned; }
- SC * operator ->() const { return m_ptr; }
- SC & operator *() const { return *m_ptr; }
- SC * get() const { return m_ptr; }
+ pointer operator ->() const noexcept { return m_ptr; }
+ typename std::add_lvalue_reference<element_type>::type operator *() const noexcept { return *m_ptr; }
+ pointer get() const noexcept { return m_ptr; }
+
+ deleter_type& get_deleter() noexcept { return m_deleter; }
+ const deleter_type& get_deleter() const noexcept { return m_deleter; }
+
private:
- SC *m_ptr;
+ pointer m_ptr;
D m_deleter;
bool m_is_owned;
};
- template <typename T>
- using unique_ptr = std::unique_ptr<T, pdefault_deleter<T>>;
-
- template<typename T, typename... Args>
- plib::unique_ptr<T> make_unique(Args&&... args)
- {
- return plib::unique_ptr<T>(pnew<T>(std::forward<Args>(args)...));
- }
-
- template<typename T, typename... Args>
- static owned_ptr<T> make_owned(Args&&... args)
- {
- owned_ptr<T> a(pnew<T>(std::forward<Args>(args)...), true);
- return std::move(a);
- }
-
//============================================================
- // Aligned allocator for use with containers
+ // Arena allocator for use with containers
//============================================================
- template <class T, std::size_t ALIGN = alignof(T)>
- class aligned_allocator
+ template <class ARENA, class T, std::size_t ALIGN = alignof(T)>
+ class arena_allocator
{
public:
using value_type = T;
static constexpr const std::size_t align_size = ALIGN;
+ using arena_type = ARENA;
static_assert(align_size >= alignof(T) && (align_size % alignof(T)) == 0,
"ALIGN must be greater than alignof(T) and a multiple");
- aligned_allocator() noexcept = default;
- ~aligned_allocator() noexcept = default;
+ arena_allocator() noexcept
+ : m_a(arena_type::instance())
+ { }
+
+ ~arena_allocator() noexcept = default;
- aligned_allocator(const aligned_allocator&) noexcept = default;
- aligned_allocator& operator=(const aligned_allocator&) noexcept = delete;
+ arena_allocator(const arena_allocator &rhs) noexcept : m_a(rhs.m_a) { printf("copy called\n"); }//= default;
+ arena_allocator& operator=(const arena_allocator&) noexcept = delete;
- aligned_allocator(aligned_allocator&&) noexcept = default;
- aligned_allocator& operator=(aligned_allocator&&) = delete;
+ arena_allocator(arena_allocator&&) noexcept = default;
+ arena_allocator& operator=(arena_allocator&&) = delete;
+
+ arena_allocator(arena_type & a) noexcept : m_a(a)
+ {
+ }
template <class U>
- aligned_allocator(const aligned_allocator<U, ALIGN>& rhs) noexcept
+ arena_allocator(const arena_allocator<ARENA, U, ALIGN>& rhs) noexcept
+ : m_a(rhs.m_a)
{
- unused_var(rhs);
}
template <class U> struct rebind
{
- using other = aligned_allocator<U, ALIGN>;
+ using other = arena_allocator<ARENA, U, ALIGN>;
};
T* allocate(std::size_t n)
{
- return reinterpret_cast<T *>(paligned_alloc(ALIGN, sizeof(T) * n));
+ return reinterpret_cast<T *>(m_a.allocate(ALIGN, sizeof(T) * n));
}
void deallocate(T* p, std::size_t n) noexcept
{
unused_var(n);
- pfree(p);
+ m_a.deallocate(p);
}
- template <class T1, std::size_t A1, class U, std::size_t A2>
- friend bool operator==(const aligned_allocator<T1, A1>& lhs,
- const aligned_allocator<U, A2>& rhs) noexcept;
+ template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2>
+ friend bool operator==(const arena_allocator<AR1, T1, A1>& lhs,
+ const arena_allocator<AR2, T2, A2>& rhs) noexcept;
- template <class U, std::size_t A> friend class aligned_allocator;
+ template <class AU, class U, std::size_t A> friend class arena_allocator;
+ private:
+ arena_type &m_a;
};
- template <class T1, std::size_t A1, class U, std::size_t A2>
- /*friend*/ inline bool operator==(const aligned_allocator<T1, A1>& lhs,
- const aligned_allocator<U, A2>& rhs) noexcept
+ template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2>
+ inline bool operator==(const arena_allocator<AR1, T1, A1>& lhs,
+ const arena_allocator<AR2, T2, A2>& rhs) noexcept
{
- unused_var(lhs, rhs);
- return A1 == A2;
+ return A1 == A2 && rhs.m_a == lhs.m_a;
}
- template <class T1, std::size_t A1, class U, std::size_t A2>
- /*friend*/ inline bool operator!=(const aligned_allocator<T1, A1>& lhs,
- const aligned_allocator<U, A2>& rhs) noexcept
+ template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2>
+ inline bool operator!=(const arena_allocator<AR1, T1, A1>& lhs,
+ const arena_allocator<AR2, T2, A2>& rhs) noexcept
{
return !(lhs == rhs);
}
//============================================================
+ // Memory allocation
+ //============================================================
+
+ struct aligned_arena
+ {
+ static constexpr const bool is_stateless = true;
+ template <class T, std::size_t ALIGN = alignof(T)>
+ using allocator_type = arena_allocator<aligned_arena, T, ALIGN>;
+
+ template <typename T>
+ using owned_pool_ptr = plib::owned_ptr<T, arena_deleter<aligned_arena, T>>;
+
+ static inline aligned_arena &instance()
+ {
+ static aligned_arena s_arena;
+ return s_arena;
+ }
+
+ static inline void *allocate( size_t alignment, size_t size )
+ {
+ #if (USE_ALIGNED_ALLOCATION)
+ #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
+ return _aligned_malloc(size, alignment);
+ #elif defined(__APPLE__)
+ void* p;
+ if (::posix_memalign(&p, alignment, size) != 0) {
+ p = nullptr;
+ }
+ return p;
+ #else
+ return aligned_alloc(alignment, size);
+ #endif
+ #else
+ unused_var(alignment);
+ return ::operator new(size);
+ #endif
+ }
+
+ static inline void deallocate( void *ptr )
+ {
+ #if (USE_ALIGNED_ALLOCATION)
+ // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
+ free(ptr);
+ #else
+ ::operator delete(ptr);
+ #endif
+ }
+
+ template<typename T, typename... Args>
+ owned_pool_ptr<T> make_poolptr(Args&&... args)
+ {
+ auto *mem = allocate(alignof(T), sizeof(T));
+ return owned_pool_ptr<T>(new (mem) T(std::forward<Args>(args)...), true, arena_deleter<aligned_arena, T>(*this));
+ }
+
+ };
+
+ template <typename T, std::size_t ALIGN>
+ /*inline */ C14CONSTEXPR T *assume_aligned_ptr(T *p) noexcept
+ {
+ static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)");
+ static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
+ //auto t = reinterpret_cast<std::uintptr_t>(p);
+ //if (t & (ALIGN-1))
+ // printf("alignment error!");
+#if (USE_ALIGNED_HINTS)
+ return reinterpret_cast<T *>(__builtin_assume_aligned(p, ALIGN));
+#else
+ return p;
+#endif
+ }
+
+ template <typename T, std::size_t ALIGN>
+ constexpr const T *assume_aligned_ptr(const T *p) noexcept
+ {
+ static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)");
+ static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
+#if (USE_ALIGNED_HINTS)
+ return reinterpret_cast<const T *>(__builtin_assume_aligned(p, ALIGN));
+#else
+ return p;
+#endif
+ }
+
+ // FIXME: remove
+ template<typename T, typename... Args>
+ inline T *pnew(Args&&... args)
+ {
+ auto *p = aligned_arena::allocate(alignof(T), sizeof(T));
+ return new(p) T(std::forward<Args>(args)...);
+ }
+
+ template<typename T>
+ inline void pdelete(T *ptr)
+ {
+ ptr->~T();
+ aligned_arena::deallocate(ptr);
+ }
+
+
+ template <typename T>
+ using unique_ptr = std::unique_ptr<T, arena_deleter<aligned_arena, T>>;
+
+ template<typename T, typename... Args>
+ plib::unique_ptr<T> make_unique(Args&&... args)
+ {
+ return plib::unique_ptr<T>(pnew<T>(std::forward<Args>(args)...));
+ }
+
+#if 0
+ template<typename T, typename... Args>
+ static owned_ptr<T> make_owned(Args&&... args)
+ {
+ return owned_ptr<T>(pnew<T>(std::forward<Args>(args)...), true);
+ }
+#endif
+
+
+ template <class T, std::size_t ALIGN = alignof(T)>
+ using aligned_allocator = aligned_arena::allocator_type<T, ALIGN>;
+
+ //============================================================
// traits to determine alignment size and stride size
// from types supporting alignment
//============================================================
@@ -321,14 +379,7 @@ namespace plib {
{
static constexpr const std::size_t align_size = alignof(std::max_align_t);
static constexpr const std::size_t value_size = sizeof(typename T::value_type);
-#if 0
- static constexpr const std::size_t stride_size =
- ((value_size % align_size) == 0 ? 1 //T is a multiple of align_size
- : ((align_size % value_size) != 0 ? align_size // align_size is not a multiple of T
- : align_size / value_size));
-#else
static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size;
-#endif
};
template <typename T>
@@ -336,14 +387,7 @@ namespace plib {
{
static constexpr const std::size_t align_size = T::align_size;
static constexpr const std::size_t value_size = sizeof(typename T::value_type);
-#if 0
- static constexpr const std::size_t stride_size =
- ((value_size % align_size) == 0 ? 1 //T is a multiple of align_size
- : ((align_size % value_size) != 0 ? align_size // align_size is not a multiple of T
- : align_size / value_size));
-#else
static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size;
-#endif
};
//============================================================