diff options
Diffstat (limited to 'src/lib/netlist/plib/palloc.h')
-rw-r--r-- | src/lib/netlist/plib/palloc.h | 513 |
1 files changed, 129 insertions, 384 deletions
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index 15fede3a99b..a35bc50ff17 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -8,427 +8,172 @@ #ifndef PALLOC_H_ #define PALLOC_H_ -#include "pconfig.h" #include "pstring.h" -#include "ptypes.h" -#include <cstddef> -#include <cstdlib> -#include <memory> -#include <type_traits> -#include <utility> #include <vector> - -#if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) -#include <malloc.h> -#endif +#include <memory> namespace plib { - //============================================================ - // Standard arena_deleter - //============================================================ - - template <typename P, typename T> - struct arena_deleter - { - //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; - } - - constexpr arena_deleter(arena_storage_type a = arena_storage_type()) noexcept - : m_a(a) { } - - template<typename PU, typename U, typename = typename - std::enable_if<std::is_convertible< U*, T*>::value>::type> - arena_deleter(const arena_deleter<PU, U> &rhs) noexcept : m_a(rhs.m_a) { } - - void operator()(T *p) //const - { - /* call destructor */ - p->~T(); - getref(m_a).deallocate(p); - } - //private: - arena_storage_type m_a; - }; - - //============================================================ - // 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_deleter(), m_is_owned(true) { } - - template <typename, typename> - friend class owned_ptr; - - owned_ptr(pointer p, bool owned) noexcept - : m_ptr(p), m_deleter(), m_is_owned(owned) - { } - - owned_ptr(pointer p, bool owned, D deleter) noexcept - : m_ptr(p), m_deleter(deleter), m_is_owned(owned) - { } - - - owned_ptr(const owned_ptr &r) = delete; - owned_ptr & operator =(owned_ptr &r) = delete; - - template<typename DC, typename DC_D> - owned_ptr & operator =(owned_ptr<DC, DC_D> &&r) - { - if (m_is_owned && (m_ptr != nullptr)) - //delete m_ptr; - m_deleter(m_ptr); - 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; - return *this; - } - - owned_ptr(owned_ptr &&r) noexcept - : m_ptr(r.m_ptr) - , m_deleter(r.m_deleter) - , m_is_owned(r.m_is_owned) - { - r.m_is_owned = false; - r.m_ptr = nullptr; - } - - owned_ptr &operator=(owned_ptr &&r) noexcept - { - if (m_is_owned && (m_ptr != nullptr)) - //delete m_ptr; - m_deleter(m_ptr); - m_is_owned = r.m_is_owned; - m_ptr = r.m_ptr; - m_deleter = std::move(r.m_deleter); - r.m_is_owned = false; - r.m_ptr = nullptr; - return *this; - } - - 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()) - { - r.release(); - } - - ~owned_ptr() noexcept - { - if (m_is_owned && (m_ptr != nullptr)) - { - //delete m_ptr; - m_deleter(m_ptr); - } - m_is_owned = false; - m_ptr = nullptr; - } - - /** - * \brief Return @c true if the stored pointer is not null. - */ - explicit operator bool() const noexcept { return m_ptr != nullptr; } - - pointer release() - { - pointer tmp = m_ptr; - m_is_owned = false; - m_ptr = nullptr; - return tmp; - } - - bool is_owned() const { return m_is_owned; } - - 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: - pointer m_ptr; - D m_deleter; - bool m_is_owned; - }; - - //============================================================ - // Arena allocator for use with containers - //============================================================ - - template <class ARENA, class T, std::size_t ALIGN = alignof(T)> - class arena_allocator +//============================================================ +// Memory allocation +//============================================================ + +template<typename T, typename... Args> +T *palloc(Args&&... args) +{ + return new T(std::forward<Args>(args)...); +} + +template<typename T> +void pfree(T *ptr) +{ + delete ptr; +} + +template<typename T> +T* palloc_array(const std::size_t num) +{ + return new T[num](); +} + +template<typename T> +void pfree_array(T *ptr) +{ + delete [] ptr; +} + +template<typename T, typename... Args> +std::unique_ptr<T> make_unique(Args&&... args) +{ + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} + +template<typename BC, typename DC, typename... Args> +static std::unique_ptr<BC> make_unique_base(Args&&... args) +{ + std::unique_ptr<BC> ret(new DC(std::forward<Args>(args)...)); + return ret; +} + +template <typename SC> +class owned_ptr +{ +private: + owned_ptr() + : m_ptr(nullptr), m_is_owned(true) { } +public: + owned_ptr(SC *p, bool owned) noexcept + : m_ptr(p), m_is_owned(owned) + { } + + owned_ptr(const owned_ptr &r) = delete; + owned_ptr & operator =(owned_ptr &r) = delete; + + template<typename DC> + owned_ptr & operator =(owned_ptr<DC> &&r) { - 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"); - - arena_allocator() noexcept - : m_a(arena_type::instance()) - { } - - ~arena_allocator() noexcept = default; - - arena_allocator(const arena_allocator &rhs) noexcept = default; - arena_allocator& operator=(const arena_allocator&) noexcept = 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> - arena_allocator(const arena_allocator<ARENA, U, ALIGN>& rhs) noexcept - : m_a(rhs.m_a) - { - } - - template <class U> struct rebind - { - using other = arena_allocator<ARENA, U, ALIGN>; - }; - - T* allocate(std::size_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); - m_a.deallocate(p); - } - - 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 AU, class U, std::size_t A> friend class arena_allocator; - private: - arena_type &m_a; - }; - - 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 A1 == A2 && rhs.m_a == lhs.m_a; - } - 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); + if (m_is_owned && (m_ptr != nullptr)) + delete m_ptr; + m_is_owned = r.m_is_owned; + m_ptr = r.m_ptr; + r.m_is_owned = false; + r.m_ptr = nullptr; + return *this; } - //============================================================ - // Memory allocation - //============================================================ - - struct aligned_arena + owned_ptr(owned_ptr &&r) noexcept { - 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 + m_is_owned = r.m_is_owned; + m_ptr = r.m_ptr; + r.m_is_owned = false; + r.m_ptr = nullptr; } - template <typename T, std::size_t ALIGN> - constexpr const T *assume_aligned_ptr(const T *p) noexcept + template<typename DC> + owned_ptr(owned_ptr<DC> &&r) 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 + m_ptr = static_cast<SC *>(r.get()); + m_is_owned = r.is_owned(); + r.release(); } - // FIXME: remove - template<typename T, typename... Args> - inline T *pnew(Args&&... args) + ~owned_ptr() { - auto *p = aligned_arena::allocate(alignof(T), sizeof(T)); - return new(p) T(std::forward<Args>(args)...); + if (m_is_owned && (m_ptr != nullptr)) + delete m_ptr; + m_is_owned = false; + m_ptr = nullptr; } - - template<typename T> - inline void pdelete(T *ptr) + template<typename DC, typename... Args> + static owned_ptr Create(Args&&... args) { - ptr->~T(); - aligned_arena::deallocate(ptr); + owned_ptr a; + DC *x = new DC(std::forward<Args>(args)...); + a.m_ptr = static_cast<SC *>(x); + return std::move(a); } - - 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) + template<typename... Args> + static owned_ptr Create(Args&&... args) { - return plib::unique_ptr<T>(pnew<T>(std::forward<Args>(args)...)); + owned_ptr a; + a.m_ptr = new SC(std::forward<Args>(args)...); + return std::move(a); } - -#if 0 - template<typename T, typename... Args> - static owned_ptr<T> make_owned(Args&&... args) + SC * release() { - return owned_ptr<T>(pnew<T>(std::forward<Args>(args)...), true); + SC *tmp = m_ptr; + m_is_owned = false; + m_ptr = nullptr; + return tmp; } -#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 - //============================================================ - PDEFINE_HAS_MEMBER(has_align, align_size); + bool is_owned() const { return m_is_owned; } - template <typename T, typename X = void> - struct align_traits - { - 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); - static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size; - }; + SC * operator ->() const { return m_ptr; } + SC & operator *() const { return *m_ptr; } + SC * get() const { return m_ptr; } +private: + SC *m_ptr; + bool m_is_owned; +}; - template <typename T> - struct align_traits<T, typename std::enable_if<has_align<T>::value, void>::type> +class mempool +{ +private: + struct block { - static constexpr const std::size_t align_size = T::align_size; - static constexpr const std::size_t value_size = sizeof(typename T::value_type); - static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size; + block() : m_num_alloc(0), m_free(0), cur_ptr(nullptr), data(nullptr) { } + std::size_t m_num_alloc; + std::size_t m_free; + char *cur_ptr; + char *data; }; - //============================================================ - // Aligned vector - //============================================================ + size_t new_block(); + size_t mininfosize(); - // FIXME: needs a separate file - template <class T, std::size_t ALIGN = alignof(T)> - class aligned_vector : public std::vector<T, aligned_allocator<T, ALIGN>> + struct info { - public: - using base = std::vector<T, aligned_allocator<T, ALIGN>>; + info() : m_block(0) { } + size_t m_block; + }; - using reference = typename base::reference; - using const_reference = typename base::const_reference; - using pointer = typename base::pointer; - using const_pointer = typename base::const_pointer; - using size_type = typename base::size_type; + size_t m_min_alloc; + size_t m_min_align; - using base::base; + std::vector<block> m_blocks; - C14CONSTEXPR reference operator[](size_type i) noexcept - { - return assume_aligned_ptr<T, ALIGN>(&(base::operator[](0)))[i]; - } - constexpr const_reference operator[](size_type i) const noexcept - { - return assume_aligned_ptr<T, ALIGN>(&(base::operator[](0)))[i]; - } +public: + mempool(size_t min_alloc, size_t min_align); + ~mempool(); - pointer data() noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); } - const_pointer data() const noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); } + void *alloc(size_t size); + void free(void *ptr); - }; +}; -} // namespace plib +} #endif /* PALLOC_H_ */ |