Skip to content

Commit

Permalink
LocalPointer: improving alignment handling (#489)
Browse files Browse the repository at this point in the history
* LocalPointer: improving alignment handling

* Apply clang-format

* Fixing CI failures

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
jatinchowdhury18 and github-actions[bot] authored Feb 9, 2024
1 parent 003e5fa commit f405ad2
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 1 deletion.
12 changes: 12 additions & 0 deletions modules/common/chowdsp_core/Types/chowdsp_TypeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ struct is_specialization_of<OuterType<TypeArgs...>, OuterType> final : std::true
template <typename CompleteType, template <typename...> class OuterType>
static constexpr bool is_specialization_of_v = is_specialization_of<CompleteType, OuterType>::value;

template <typename T>
struct is_complete_type
{
template <typename U>
static auto test (U*) -> std::integral_constant<bool, sizeof (U) == sizeof (U)>;
static auto test (...) -> std::false_type;
static constexpr auto value = ! std::is_same_v<decltype (test (static_cast<T*> (nullptr))), std::false_type>;
};

template <typename T>
static constexpr auto is_complete_type_v = is_complete_type<T>::value;

/**
* An empty struct intended to be used with std::conditional_t
* to effectively "disable" some member of a struct/class.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ namespace chowdsp
{
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4324) // structure was padded due to alignment specifier

#ifndef DOXYGEN
namespace local_pointer_detail
{
template <typename T>
constexpr size_t get_alignment()
{
if constexpr (is_complete_type_v<T>)
return alignof (T);
return 8;
}
} // namespace local_pointer_detail
#endif

/**
* A generic "owning" pointer constructed using local storage.
*
Expand All @@ -15,7 +28,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4324) // structure was padded due to alignment
* Make sure that no other type (e.g. std::unique_ptr) tries to take ownership
* of the pointer being stored here, since that will result in a double-delete.
*/
template <typename T, size_t MaxSize, size_t Alignment = 0>
template <typename T, size_t MaxSize, size_t Alignment = local_pointer_detail::get_alignment<T>()>
class LocalPointer
{
public:
Expand All @@ -40,6 +53,7 @@ class LocalPointer
jassert (pointer == nullptr);
jassert (other.pointer == nullptr);
juce::ignoreUnused (other);
return *this;
}

/**
Expand All @@ -52,6 +66,8 @@ class LocalPointer
C* emplace (Args&&... args)
{
static_assert (MaxSize >= sizeof (C), "Type is too large to fit into MaxSize bytes!");
static_assert (Alignment % alignof (C) == 0, "Type alignments are incompatible!");

reset();
pointer = new (data.data()) C (std::forward<Args> (args)...);
return reinterpret_cast<C*> (pointer);
Expand Down
7 changes: 7 additions & 0 deletions tests/common_tests/chowdsp_core_test/TypeTraitsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,11 @@ TEST_CASE ("Type Traits Test", "[common][types]")
STATIC_REQUIRE (IsMapLike<std::unordered_map<int, int>>);
STATIC_REQUIRE (IsMapLike<std::map<int, int>>);
STATIC_REQUIRE_FALSE (IsMapLike<std::vector<int>>);

struct A
{
};
struct B;
STATIC_REQUIRE (chowdsp::is_complete_type_v<A>);
STATIC_REQUIRE_FALSE (chowdsp::is_complete_type_v<B>);
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,29 @@ TEST_CASE ("Local Pointer Test", "[common][data-structures]")
REQUIRE (ptr->xx == 45);
REQUIRE (childPtr->yy == 46);
}

JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4324 4319)
static constexpr size_t testAlignment = 32;
SECTION ("Alignment Known")
{
struct alignas (testAlignment) Test
{
};
chowdsp::LocalPointer<Test, 64> ptr;
ptr.emplace();
const auto alignedPtr = juce::snapPointerToAlignment (ptr.get(), testAlignment);
REQUIRE (alignedPtr == ptr.get());
}

SECTION ("Alignment Forward Declared")
{
chowdsp::LocalPointer<struct Test, 64, testAlignment> ptr;
struct alignas (testAlignment) Test
{
};
ptr.emplace();
const auto alignedPtr = juce::snapPointerToAlignment (ptr.get(), testAlignment);
REQUIRE (alignedPtr == ptr.get());
}
JUCE_END_IGNORE_WARNINGS_MSVC
}

0 comments on commit f405ad2

Please sign in to comment.