mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-24 00:10:02 -06:00
2c7806c6b5
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.
207 lines
4.8 KiB
C++
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
|