mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-25 16:51:00 -06:00
227 lines
5.6 KiB
C++
227 lines
5.6 KiB
C++
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
// vi: set et ts=4 sw=4 sts=4:
|
|
/*
|
|
This file is part of the Open Porous Media project (OPM).
|
|
|
|
OPM is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
OPM is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
Consult the COPYING file in the top-level source directory of this
|
|
module for the precise wording of the license and the list of
|
|
copyright holders.
|
|
*/
|
|
/*!
|
|
* \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
|