diff --git a/external/jsl/include/jsl/bits/memory/aligned_unique_ptr.tcc b/external/jsl/include/jsl/bits/memory/aligned_unique_ptr.tcc new file mode 100644 index 00000000..168c934a --- /dev/null +++ b/external/jsl/include/jsl/bits/memory/aligned_unique_ptr.tcc @@ -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 +void aligned_ptr_delete::operator()(T *p) const noexcept +{ + aligned_allocator allocator; + allocator.destroy(p); + allocator.deallocate(p, 0); +} + +template +aligned_unique_ptr::single_element, Al> +make_aligned(Args &&... args) +{ + struct allocation_delete { + void operator()(T *p) const noexcept + { + aligned_allocator allocator; + allocator.destroy(p); + } + }; + aligned_allocator allocator; + std::unique_ptr allocation(allocator.allocate(1, nullptr)); + allocator.construct(allocation.get(), std::forward(args)...); + return aligned_unique_ptr(allocation.release()); +} + +} // namespace jsl diff --git a/external/jsl/include/jsl/memory b/external/jsl/include/jsl/memory new file mode 100644 index 00000000..a5ff5ec5 --- /dev/null +++ b/external/jsl/include/jsl/memory @@ -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 + +namespace jsl { + +template +struct aligned_ptr_delete { + void operator()(T *p) const noexcept; +}; + +template +using aligned_unique_ptr = std::unique_ptr>; + +//------------------------------------------------------------------------------ + +template struct make_aligned_traits; +template struct make_aligned_traits { struct invalid {}; }; +template struct make_aligned_traits { struct invalid {}; }; +template struct make_aligned_traits { using single_element = T; }; + +//------------------------------------------------------------------------------ + +template +aligned_unique_ptr::single_element, Al> +make_aligned(Args &&... args); + +template +typename make_aligned_traits::invalid +make_aligned(Args &&... args) = delete; + +} // namespace jsl + +#include "bits/memory/aligned_unique_ptr.tcc" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2e5f70a9..9ae219db 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -49,6 +49,7 @@ set(SFIZZ_TEST_SOURCES LFOT.cpp MessagingT.cpp OversamplerT.cpp + MemoryT.cpp DataHelpers.h DataHelpers.cpp ) diff --git a/tests/MemoryT.cpp b/tests/MemoryT.cpp new file mode 100644 index 00000000..bf7b0497 --- /dev/null +++ b/tests/MemoryT.cpp @@ -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 +#include +#include + +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> ptrs(numAllocations); + + for (size_t i = 0; i < numAllocations; ++i) { + ptrs[i] = jsl::make_aligned(i); + REQUIRE(numLiveObjects == i + 1); + + Object *obj = ptrs[i].get(); + REQUIRE(obj->id == i); + + uintptr_t addr = reinterpret_cast(obj); + REQUIRE(addr % alignment == 0); + } + + ptrs.clear(); + REQUIRE(numLiveObjects == 0); +}