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.h124
1 files changed, 84 insertions, 40 deletions
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h
index 44f3bdb395e..c7aad9372d3 100644
--- a/src/lib/netlist/plib/palloc.h
+++ b/src/lib/netlist/plib/palloc.h
@@ -28,19 +28,21 @@ namespace plib {
// Memory allocation
//============================================================
-#if (USE_ALIGNED_OPTIMIZATIONS)
+ static constexpr bool is_pow2(std::size_t v) noexcept { return !(v & (v-1)); }
+
+#if (USE_ALIGNED_ALLOCATION)
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;
+ void* p;
+ if (::posix_memalign(&p, alignment, size) != 0) {
+ p = nullptr;
+ }
+ return p;
#else
- return aligned_alloc(alignment, size);
+ return aligned_alloc(alignment, size);
#endif
}
@@ -79,19 +81,35 @@ namespace plib {
{
::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>
inline C14CONSTEXPR 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)
{
@@ -124,8 +142,8 @@ namespace plib {
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 { }
+ std::enable_if<std::is_convertible< U*, T*>::value>::type>
+ pdefault_deleter(const pdefault_deleter<U>&) noexcept { }
void operator()(T *p) const
{
@@ -245,33 +263,38 @@ namespace plib {
return std::move(a);
}
+ //============================================================
+ // Aligned allocator for use with containers
+ //============================================================
+
template <class T, std::size_t ALIGN = alignof(T)>
class aligned_allocator
{
public:
- using value_type = T;
+ using value_type = T;
+ static constexpr const std::size_t align_size = (USE_ALIGNED_ALLOCATION) ? ALIGN : alignof(std::max_align_t);
- static_assert(ALIGN >= alignof(T) && (ALIGN % alignof(T)) == 0,
- "ALIGN must be greater than alignof(T) and a multiple");
+ 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;
+ aligned_allocator() noexcept = default;
+ ~aligned_allocator() noexcept = default;
- aligned_allocator(const aligned_allocator&) noexcept = default;
- aligned_allocator& operator=(const aligned_allocator&) noexcept = delete;
+ aligned_allocator(const aligned_allocator&) noexcept = default;
+ aligned_allocator& operator=(const aligned_allocator&) noexcept = delete;
- aligned_allocator(aligned_allocator&&) noexcept = default;
- aligned_allocator& operator=(aligned_allocator&&) = delete;
+ aligned_allocator(aligned_allocator&&) noexcept = default;
+ aligned_allocator& operator=(aligned_allocator&&) = delete;
- template <class U>
- aligned_allocator(const aligned_allocator<U, ALIGN>& rhs) noexcept
- {
- unused_var(rhs);
- }
+ template <class U>
+ aligned_allocator(const aligned_allocator<U, ALIGN>& rhs) noexcept
+ {
+ unused_var(rhs);
+ }
- template <class U> struct rebind
+ template <class U> struct rebind
{
- using other = aligned_allocator<U, ALIGN>;
+ using other = aligned_allocator<U, ALIGN>;
};
T* allocate(std::size_t n)
@@ -306,12 +329,38 @@ namespace plib {
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
+ //============================================================
+ // traits to determine alignment size and stride size
+ // from types supporting alignment
+ //============================================================
+
+ PDEFINE_HAS_MEMBER(has_align, align_size);
+
+ 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 stride_size =
+ (sizeof(T) % align_size == 0 ? 1 //T is a multiple of align_size
+ : (align_size % sizeof(T) != 0 ? align_size // align_size is not a multiple of T
+ : align_size / sizeof(T)));
+ };
+
+ template <typename T>
+ struct align_traits<T, typename std::enable_if<has_align<T>::value, void>::type>
+ {
+ static constexpr const std::size_t align_size = T::align_size;
+ static constexpr const std::size_t stride_size =
+ (sizeof(T) % align_size == 0 ? 1 //T is a multiple of align_size
+ : (align_size % sizeof(T) != 0 ? align_size // align_size is not a multiple of T
+ : align_size / sizeof(T)));
+ };
+
+ //============================================================
+ // Aligned vector
+ //============================================================
+
+ // 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>>
{
@@ -326,13 +375,13 @@ namespace plib {
using base::base;
- reference operator[](size_type i) noexcept
+ C14CONSTEXPR reference operator[](size_type i) noexcept
{
- return assume_aligned_ptr<T, ALIGN>(this->data())[i];
+ return assume_aligned_ptr<T, ALIGN>(&((*this)[0]))[i];
}
constexpr const_reference operator[](size_type i) const noexcept
{
- return assume_aligned_ptr<T, ALIGN>(this->data())[i];
+ return assume_aligned_ptr<T, ALIGN>(&((*this)[0]))[i];
}
pointer data() noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); }
@@ -340,11 +389,6 @@ namespace plib {
};
-
-#endif
-
-
-
} // namespace plib
#endif /* PALLOC_H_ */