Add jsl::aligned_unique_ptr and jsl::make_aligned

This commit is contained in:
Jean Pierre Cimalando 2021-09-22 03:12:52 +02:00
parent 4f0712c489
commit 3fd0d4ee5d
4 changed files with 123 additions and 0 deletions

View file

@ -0,0 +1,39 @@
// -*- C++ -*-
// SPDX-License-Identifier: BSL-1.0
//
// Copyright Jean Pierre Cimalando 2018-2020.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "../../memory"
namespace jsl {
template <class T, std::size_t Al>
void aligned_ptr_delete<T, Al>::operator()(T *p) const noexcept
{
aligned_allocator<T, Al> allocator;
allocator.destroy(p);
allocator.deallocate(p, 0);
}
template <class T, std::size_t Al, class... Args>
aligned_unique_ptr<typename make_aligned_traits<T>::single_element, Al>
make_aligned(Args &&... args)
{
struct allocation_delete {
void operator()(T *p) const noexcept
{
aligned_allocator<T, Al> allocator;
allocator.destroy(p);
}
};
aligned_allocator<T, Al> allocator;
std::unique_ptr<T, allocation_delete> allocation(allocator.allocate(1, nullptr));
allocator.construct(allocation.get(), std::forward<Args>(args)...);
return aligned_unique_ptr<T, Al>(allocation.release());
}
} // namespace jsl

42
external/jsl/include/jsl/memory vendored Normal file
View file

@ -0,0 +1,42 @@
// -*- C++ -*-
// SPDX-License-Identifier: BSL-1.0
//
// Copyright Jean Pierre Cimalando 2018-2020.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "./allocator"
#include <memory>
namespace jsl {
template <class T, std::size_t Al>
struct aligned_ptr_delete {
void operator()(T *p) const noexcept;
};
template <class T, std::size_t Al>
using aligned_unique_ptr = std::unique_ptr<T, aligned_ptr_delete<T, Al>>;
//------------------------------------------------------------------------------
template <class T> struct make_aligned_traits;
template <class T, size_t N> struct make_aligned_traits<T[N]> { struct invalid {}; };
template <class T> struct make_aligned_traits<T[]> { struct invalid {}; };
template <class T> struct make_aligned_traits { using single_element = T; };
//------------------------------------------------------------------------------
template <class T, std::size_t Al, class... Args>
aligned_unique_ptr<typename make_aligned_traits<T>::single_element, Al>
make_aligned(Args &&... args);
template <class T, std::size_t Al, class... Args>
typename make_aligned_traits<T>::invalid
make_aligned(Args &&... args) = delete;
} // namespace jsl
#include "bits/memory/aligned_unique_ptr.tcc"

View file

@ -49,6 +49,7 @@ set(SFIZZ_TEST_SOURCES
LFOT.cpp LFOT.cpp
MessagingT.cpp MessagingT.cpp
OversamplerT.cpp OversamplerT.cpp
MemoryT.cpp
DataHelpers.h DataHelpers.h
DataHelpers.cpp DataHelpers.cpp
) )

41
tests/MemoryT.cpp Normal file
View file

@ -0,0 +1,41 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "catch2/catch.hpp"
#include <jsl/memory>
#include <vector>
#include <cstdint>
TEST_CASE("[Memory] Aligned unique pointers")
{
constexpr size_t numAllocations = 128;
constexpr size_t alignment = 1024;
static size_t numLiveObjects;
numLiveObjects = 0;
struct Object {
explicit Object(size_t id) : id(id) { ++numLiveObjects; }
~Object() { --numLiveObjects; }
size_t id {};
};
std::vector<jsl::aligned_unique_ptr<Object, alignment>> ptrs(numAllocations);
for (size_t i = 0; i < numAllocations; ++i) {
ptrs[i] = jsl::make_aligned<Object, alignment>(i);
REQUIRE(numLiveObjects == i + 1);
Object *obj = ptrs[i].get();
REQUIRE(obj->id == i);
uintptr_t addr = reinterpret_cast<uintptr_t>(obj);
REQUIRE(addr % alignment == 0);
}
ptrs.clear();
REQUIRE(numLiveObjects == 0);
}