diff options
author | 2019-02-22 11:09:58 -0300 | |
---|---|---|
committer | 2019-02-22 11:09:58 -0300 | |
commit | 3972e74ee9e4095b6b151894e77e6bdfb449626c (patch) | |
tree | 993529a9c291501ed4d2c4733424c8b5c6373370 /src/lib/netlist/plib/palloc.h | |
parent | b58f948528ffc9899b71481e813f04a3049ea1bf (diff) | |
parent | 9ec1ab5d1aa23610e7cff20fad5f05cfbe1aa052 (diff) |
Merge branch 'master' of https://github.com/Robbbert/hbmame
Diffstat (limited to 'src/lib/netlist/plib/palloc.h')
-rw-r--r-- | src/lib/netlist/plib/palloc.h | 193 |
1 files changed, 183 insertions, 10 deletions
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index c70aaa392d7..45c19ef7b3a 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -8,45 +8,124 @@ #ifndef PALLOC_H_ #define PALLOC_H_ +#include "pconfig.h" #include "pstring.h" #include "ptypes.h" #include <cstddef> +#include <cstdlib> #include <memory> #include <utility> #include <vector> +#if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) +#include <malloc.h> +#endif + namespace plib { //============================================================ // Memory allocation //============================================================ +#if (USE_ALIGNED_OPTIMIZATIONS) + static inline void *paligned_alloc( size_t alignment, size_t size ) + { +#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 + } + + static inline void pfree( void *ptr ) + { + free(ptr); + } + + template <typename T, std::size_t ALIGN> + inline C14CONSTEXPR T *assume_aligned_ptr(T *p) noexcept + { + return reinterpret_cast<T *>(__builtin_assume_aligned(p, ALIGN)); + } + + template <typename T, std::size_t ALIGN> + inline C14CONSTEXPR const T *assume_aligned_ptr(const T *p) noexcept + { + return reinterpret_cast<const T *>(__builtin_assume_aligned(p, ALIGN)); + } +#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); + } + + template <typename T, std::size_t ALIGN> + inline C14CONSTEXPR T *assume_aligned_ptr(T *p) noexcept + { + return p; + } + + template <typename T, std::size_t ALIGN> + inline C14CONSTEXPR const T *assume_aligned_ptr(const T *p) noexcept + { + return p; + } +#endif template<typename T, typename... Args> - T *palloc(Args&&... args) + inline T *pnew(Args&&... args) { - return new T(std::forward<Args>(args)...); + auto *p = paligned_alloc(alignof(T), sizeof(T)); + return new(p) T(std::forward<Args>(args)...); } template<typename T> - void pfree(T *ptr) + inline void pdelete(T *ptr) { - delete ptr; + ptr->~T(); + pfree(ptr); } template<typename T> - T* palloc_array(const std::size_t num) + inline T* pnew_array(const std::size_t num) { return new T[num](); } template<typename T> - void pfree_array(T *ptr) + inline void pdelete_array(T *ptr) { delete [] ptr; } - template <typename SC, typename D = std::default_delete<SC>> + template <typename T> + struct pdefault_deleter + { + constexpr pdefault_deleter() noexcept = default; + + template<typename U, typename = typename + std::enable_if<std::is_convertible< U*, T*>::value>::type> + pdefault_deleter(const pdefault_deleter<U>&) noexcept { } + + void operator()(T *p) const + { + pdelete(p); + } + }; + + template <typename SC, typename D = pdefault_deleter<SC>> class owned_ptr { public: @@ -142,19 +221,113 @@ namespace plib { bool m_is_owned; }; + template <typename T> + using unique_ptr = std::unique_ptr<T, pdefault_deleter<T>>; + template<typename T, typename... Args> - std::unique_ptr<T> make_unique(Args&&... args) + plib::unique_ptr<T> make_unique(Args&&... args) { - return std::unique_ptr<T>(new T(std::forward<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(new T(std::forward<Args>(args)...), true); + owned_ptr<T> a(pnew<T>(std::forward<Args>(args)...), true); return std::move(a); } + template <class T, std::size_t ALIGN = alignof(T)> + class aligned_allocator + { + public: + using value_type = T; + + static_assert(ALIGN >= alignof(T) && (ALIGN % alignof(T)) == 0, + "ALIGN must be greater than alignof(T) and a multiple"); + + aligned_allocator() = default; + + aligned_allocator(const aligned_allocator&) = default; + aligned_allocator& operator=(const aligned_allocator&) = delete; + + template <class U> + aligned_allocator(const aligned_allocator<U, ALIGN>& rhs) noexcept + { + unused_var(rhs); + } + + template <class U> struct rebind + { + using other = aligned_allocator<U, ALIGN>; + }; + + T* allocate(std::size_t n) + { + return reinterpret_cast<T *>(paligned_alloc(ALIGN, sizeof(T) * n)); + } + + void deallocate(T* p, std::size_t n) noexcept + { + unused_var(n); + pfree(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 U, std::size_t A> friend class aligned_allocator; + }; + + 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 + { + unused_var(lhs, rhs); + return A1 == A2; + } + 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 + { + return !(lhs == rhs); + } + + // FIXME: needs to be somewhere else +#if 0 + template <class T, std::size_t ALIGN = alignof(T)> + using aligned_vector = std::vector<T, aligned_allocator<T, alignof(T)>>; + //using aligned_vector = std::vector<T, aligned_allocator<T, ALIGN>>; +#else + template <class T, std::size_t ALIGN = alignof(T)> + class aligned_vector : public std::vector<T, aligned_allocator<T, ALIGN>> + { + public: + using base = std::vector<T, aligned_allocator<T, ALIGN>>; + + using reference = typename base::reference; + using const_reference = typename base::const_reference; + using size_type = typename base::size_type; + + using base::base; + + reference operator[](size_type i) noexcept + { + return assume_aligned_ptr<T, ALIGN>(this->data())[i]; + } + constexpr const_reference operator[](size_type i) const noexcept + { + return assume_aligned_ptr<T, ALIGN>(this->data())[i]; + } + + }; + + +#endif + + + } // namespace plib #endif /* PALLOC_H_ */ |