opm-simulators/opm/models/utils/alignedallocator.hh
Markus Blatt 2c7806c6b5 Removed GPL copyright header from code licensed under Boost license.
One cannot just add another license when there are no substantial
creative changes and you are changing existing code only.

There is no need either as we can use code under Boost license next
to GPL.
2024-11-08 11:19:21 +01:00

207 lines
4.8 KiB
C++

// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*!
* \file
* \brief This is a stand-alone version of boost::alignment::aligned_allocator from Boost
* 1.58
*
* The file has been modified to assume a C++-2011 compatible compiler on a POSIX
* operating system to remove the boost dependencies which the original version
* contained. The original copyright notice for this file is:
*
<pre>
(c) 2014 Glen Joseph Fernandes
glenjofe at gmail dot com
Distributed under the Boost Software
License, Version 1.0.
http://boost.org/LICENSE_1_0.txt
</pre>
*/
#ifndef EWOMS_ALIGNED_ALLOCATOR_HH
#define EWOMS_ALIGNED_ALLOCATOR_HH
#include <utility>
#include <memory>
#include <type_traits>
#include <cassert>
namespace Opm {
namespace detail {
constexpr inline bool is_alignment(std::size_t value) noexcept
{
return (value > 0) && ((value & (value - 1)) == 0);
}
template<std::size_t N>
struct is_alignment_constant
: std::integral_constant<bool, (N > 0) && ((N & (N - 1)) == 0)>
{};
template<std::size_t A, std::size_t B>
struct min_size
: std::integral_constant<std::size_t, (A < B) ? A : B>
{ };
template<class T>
struct offset_object
{
char offset;
T object;
};
template<class T>
struct alignment_of
: min_size<sizeof(T), sizeof(offset_object<T>) - sizeof(T)>::type
{};
template<std::size_t A, std::size_t B>
struct max_align
: std::integral_constant<std::size_t,(A > B) ? A : B>
{};
template<class T>
struct max_count_of
: std::integral_constant<std::size_t, ~static_cast<std::size_t>(0) / sizeof(T)>
{};
using std::addressof;
}
inline void* aligned_alloc(std::size_t alignment,
std::size_t size) noexcept
{
assert(detail::is_alignment(alignment));
if (alignment < sizeof(void*)) {
alignment = sizeof(void*);
}
void* p;
if (::posix_memalign(&p, alignment, size) != 0) {
p = 0;
}
return p;
}
inline void aligned_free(void* ptr)
noexcept
{
::free(ptr);
}
template<class T, std::size_t Alignment>
class aligned_allocator {
static_assert(detail::is_alignment_constant<Alignment>::value, "Alignment must be powers of two!");
public:
using value_type = T;
using pointer = T*;
using const_pointer = const T*;
using void_pointer = void*;
using const_void_pointer = const void*;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using reference = T&;
using const_reference = const T&;
private:
using MaxAlign = detail::max_align<Alignment, detail::alignment_of<value_type>::value>;
public:
template<class U>
struct rebind {
using other = aligned_allocator<U, Alignment>;
};
aligned_allocator()
noexcept = default;
template<class U>
aligned_allocator(const aligned_allocator<U,
Alignment>&) noexcept {
}
pointer address(reference value) const
noexcept {
return detail::addressof(value);
}
const_pointer address(const_reference value) const
noexcept {
return detail::addressof(value);
}
pointer allocate(size_type size,
const_void_pointer = 0) {
void* p = aligned_alloc(MaxAlign::value,
sizeof(T) * size);
if (!p && size > 0) {
throw std::bad_alloc();
}
return static_cast<T*>(p);
}
void deallocate(pointer ptr, size_type) {
aligned_free(ptr);
}
constexpr size_type max_size() const
noexcept {
return detail::max_count_of<T>::value;
}
template<class U, class... Args>
void construct(U* ptr, Args&&... args) {
void* p = ptr;
::new(p) U(std::forward<Args>(args)...);
}
template<class U>
void construct(U* ptr) {
void* p = ptr;
::new(p) U();
}
template<class U>
void destroy(U* ptr) {
(void)ptr;
ptr->~U();
}
};
template<std::size_t Alignment>
class aligned_allocator<void, Alignment> {
static_assert(detail::is_alignment_constant<Alignment>::value,
"The specified alignment is not a power of two!");
public:
using value_type = void;
using pointer = void*;
using const_pointer = const void*;
template<class U>
struct rebind {
using other = aligned_allocator<U, Alignment>;
};
};
template<class T1, class T2, std::size_t Alignment>
inline bool operator==(const aligned_allocator<T1,
Alignment>&, const aligned_allocator<T2,
Alignment>&) noexcept
{
return true;
}
template<class T1, class T2, std::size_t Alignment>
inline bool operator!=(const aligned_allocator<T1,
Alignment>&, const aligned_allocator<T2,
Alignment>&) noexcept
{
return false;
}
}
#endif