Blame include/memkind_allocator.h

Packit 345191
/*
Packit 345191
 * Copyright (C) 2019 - 2020 Intel Corporation.
Packit 345191
 * All rights reserved.
Packit 345191
 *
Packit 345191
 * Redistribution and use in source and binary forms, with or without
Packit 345191
 * modification, are permitted provided that the following conditions are met:
Packit 345191
 * 1. Redistributions of source code must retain the above copyright notice(s),
Packit 345191
 *    this list of conditions and the following disclaimer.
Packit 345191
 * 2. Redistributions in binary form must reproduce the above copyright notice(s),
Packit 345191
 *    this list of conditions and the following disclaimer in the documentation
Packit 345191
 *    and/or other materials provided with the distribution.
Packit 345191
 *
Packit 345191
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS
Packit 345191
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
Packit 345191
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
Packit 345191
 * EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit 345191
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 345191
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit 345191
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit 345191
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
Packit 345191
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
Packit 345191
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 345191
 */
Packit 345191
Packit 345191
#pragma once
Packit 345191
Packit 345191
#include <cmath>
Packit 345191
#include <map>
Packit 345191
#include <memory>
Packit 345191
#include <string>
Packit 345191
#include <exception>
Packit 345191
#include <type_traits>
Packit 345191
#include <cstddef>
Packit 345191
#include <stdexcept>
Packit 345191
Packit 345191
#include "memkind.h"
Packit 345191
Packit 345191
/*
Packit 345191
 * Header file for the C++ allocator compatible with the C++ standard library allocator concepts.
Packit 345191
 * More details in memkind(3) man page.
Packit 345191
 * Note: memory heap management is based on memkind_malloc, refer to the memkind(3) man page for more
Packit 345191
 * information.
Packit 345191
 *
Packit 345191
 * Functionality defined in this header is considered as stable API (STANDARD API).
Packit 345191
 * API standards are described in memkind(3) man page.
Packit 345191
 */
Packit 345191
namespace libmemkind
Packit 345191
{
Packit 345191
    enum class kinds {
Packit 345191
        DEFAULT = 0,
Packit 345191
        HUGETLB = 1,
Packit 345191
        INTERLEAVE = 2,
Packit 345191
        HBW = 3,
Packit 345191
        HBW_ALL = 4,
Packit 345191
        HBW_HUGETLB = 5,
Packit 345191
        HBW_ALL_HUGETLB = 6,
Packit 345191
        HBW_PREFERRED = 7,
Packit 345191
        HBW_PREFERRED_HUGETLB = 8,
Packit 345191
        HBW_INTERLEAVE = 9,
Packit 345191
        REGULAR = 10,
Packit 345191
        DAX_KMEM = 11,
Packit 345191
        DAX_KMEM_ALL = 12,
Packit 345191
        DAX_KMEM_PREFERRED = 13,
Packit 345191
    };
Packit 345191
Packit 345191
    namespace static_kind
Packit 345191
    {
Packit 345191
        template<typename T>
Packit 345191
        class allocator
Packit 345191
        {
Packit 345191
        public:
Packit 345191
            using value_type = T;
Packit 345191
            using pointer = value_type*;
Packit 345191
            using const_pointer = const value_type*;
Packit 345191
            using reference = value_type&;
Packit 345191
            using const_reference = const value_type&;
Packit 345191
            using size_type = size_t;
Packit 345191
            using difference_type = ptrdiff_t;
Packit 345191
Packit 345191
            template<class U>
Packit 345191
            struct rebind {
Packit 345191
                using other = allocator<U>;
Packit 345191
            };
Packit 345191
Packit 345191
            template<typename U>
Packit 345191
            friend class allocator;
Packit 345191
Packit 345191
#if !_GLIBCXX_USE_CXX11_ABI
Packit 345191
            /* This is a workaround for compilers (e.g GCC 4.8) that uses C++11 standard,
Packit 345191
             * but use old - non C++11 ABI */
Packit 345191
            template<typename V = void>
Packit 345191
            explicit allocator()
Packit 345191
            {
Packit 345191
                static_assert(std::is_same<V, void>::value,
Packit 345191
                              "libmemkind::static_kind::allocator cannot be compiled without CXX11 ABI");
Packit 345191
            }
Packit 345191
#endif
Packit 345191
Packit 345191
            explicit allocator(libmemkind::kinds kind)
Packit 345191
            {
Packit 345191
                switch (kind) {
Packit 345191
                    case libmemkind::kinds::DEFAULT:
Packit 345191
                        _kind = MEMKIND_DEFAULT;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::HUGETLB:
Packit 345191
                        _kind = MEMKIND_HUGETLB;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::INTERLEAVE:
Packit 345191
                        _kind = MEMKIND_INTERLEAVE;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::HBW:
Packit 345191
                        _kind = MEMKIND_HBW;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::HBW_ALL:
Packit 345191
                        _kind = MEMKIND_HBW_ALL;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::HBW_HUGETLB:
Packit 345191
                        _kind = MEMKIND_HBW_HUGETLB;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::HBW_ALL_HUGETLB:
Packit 345191
                        _kind = MEMKIND_HBW_ALL_HUGETLB;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::HBW_PREFERRED:
Packit 345191
                        _kind = MEMKIND_HBW_PREFERRED;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::HBW_PREFERRED_HUGETLB:
Packit 345191
                        _kind = MEMKIND_HBW_PREFERRED_HUGETLB;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::HBW_INTERLEAVE:
Packit 345191
                        _kind = MEMKIND_HBW_INTERLEAVE;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::REGULAR:
Packit 345191
                        _kind = MEMKIND_REGULAR;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::DAX_KMEM:
Packit 345191
                        _kind = MEMKIND_DAX_KMEM;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::DAX_KMEM_ALL:
Packit 345191
                        _kind = MEMKIND_DAX_KMEM_ALL;
Packit 345191
                        break;
Packit 345191
                    case libmemkind::kinds::DAX_KMEM_PREFERRED:
Packit 345191
                        _kind = MEMKIND_DAX_KMEM_PREFERRED;
Packit 345191
                        break;
Packit 345191
                    default:
Packit 345191
                        throw std::runtime_error("Unknown libmemkind::kinds");
Packit 345191
                        break;
Packit 345191
                }
Packit 345191
            }
Packit 345191
Packit 345191
            allocator(const allocator &other) = default;
Packit 345191
Packit 345191
            template <typename U>
Packit 345191
            allocator(const allocator<U> &other) noexcept
Packit 345191
            {
Packit 345191
                _kind = other._kind;
Packit 345191
            }
Packit 345191
Packit 345191
            allocator(allocator &&other) = default;
Packit 345191
Packit 345191
            template <typename U>
Packit 345191
            allocator(const allocator<U> &&other) noexcept
Packit 345191
            {
Packit 345191
                _kind = std::move(other._kind);
Packit 345191
            }
Packit 345191
Packit 345191
            allocator<T> &operator = (const allocator &other) = default;
Packit 345191
Packit 345191
            template <typename U>
Packit 345191
            allocator<T> &operator = (const allocator<U> &other) noexcept
Packit 345191
            {
Packit 345191
                _kind = other._kind;
Packit 345191
                return *this;
Packit 345191
            }
Packit 345191
Packit 345191
            allocator<T> &operator = (allocator &&other) = default;
Packit 345191
Packit 345191
            template <typename U>
Packit 345191
            allocator<T> &operator = (allocator<U> &&other) noexcept
Packit 345191
            {
Packit 345191
                _kind = std::move(other._kind);
Packit 345191
                return *this;
Packit 345191
            }
Packit 345191
Packit 345191
            pointer allocate(size_type n) const
Packit 345191
            {
Packit 345191
                pointer result = static_cast<pointer>(memkind_malloc(_kind, n*sizeof(T)));
Packit 345191
                if (!result) {
Packit 345191
                    throw std::bad_alloc();
Packit 345191
                }
Packit 345191
                return result;
Packit 345191
            }
Packit 345191
Packit 345191
            void deallocate(pointer p, size_type n) const
Packit 345191
            {
Packit 345191
                memkind_free(_kind, static_cast<void *>(p));
Packit 345191
            }
Packit 345191
Packit 345191
            template <class U, class... Args>
Packit 345191
            void construct(U *p, Args &&... args) const
Packit 345191
            {
Packit 345191
                ::new((void *)p) U(std::forward<Args>(args)...);
Packit 345191
            }
Packit 345191
Packit 345191
            void destroy(pointer p) const
Packit 345191
            {
Packit 345191
                p->~value_type();
Packit 345191
            }
Packit 345191
Packit 345191
            template <typename U, typename V>
Packit 345191
            friend bool operator ==(const allocator<U> &lhs, const allocator<V> &rhs;;
Packit 345191
Packit 345191
            template <typename U, typename V>
Packit 345191
            friend bool operator !=(const allocator<U> &lhs, const allocator<V> &rhs;;
Packit 345191
Packit 345191
        private:
Packit 345191
            memkind_t _kind;
Packit 345191
        };
Packit 345191
Packit 345191
        template <typename U, typename V>
Packit 345191
        bool operator ==(const allocator<U> &lhs, const allocator<V> &rhs)
Packit 345191
        {
Packit 345191
            return lhs._kind == rhs._kind;
Packit 345191
        }
Packit 345191
Packit 345191
        template <typename U, typename V>
Packit 345191
        bool operator !=(const allocator<U> &lhs, const allocator<V> &rhs)
Packit 345191
        {
Packit 345191
            return !(lhs._kind == rhs._kind);
Packit 345191
        }
Packit 345191
    }  // namespace static_kind
Packit 345191
}  // namespace libmemkind