Skip to content

Commit 1753780

Browse files
authored
Merge pull request #252 from Libvisual/c++17-mem-alloc
Core (Memory): Streamline AlignedAllocator for C++17 and add aligned allocation unit tests.
2 parents a09f4fe + 627b6cc commit 1753780

4 files changed

Lines changed: 87 additions & 65 deletions

File tree

libvisual/libvisual/lv_aligned_allocator.hpp

Lines changed: 20 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,59 @@
11
#ifndef _LV_ALIGNED_ALLOCATOR_HPP
22
#define _LV_ALIGNED_ALLOCATOR_HPP
33

4-
#include <cstddef>
5-
#include <cstdlib>
6-
#include <new>
74
#include <libvisual/lv_mem.h>
5+
#include <cstdlib>
6+
#include <limits>
7+
#include <memory>
8+
#include <stdexcept>
89

9-
namespace LV {
10-
11-
template <typename T, std::size_t alignment>
12-
struct AlignedAllocator;
13-
14-
template <std::size_t alignment>
15-
struct AlignedAllocator<void, alignment>
16-
{
17-
typedef void value_type;
18-
typedef void* pointer;
19-
typedef void const* const_pointer;
20-
21-
template <typename U>
22-
struct rebind { typedef AlignedAllocator<U, alignment> other; };
23-
};
24-
10+
namespace LV
11+
{
2512
//! Aligned memory allocator.
2613
//!
27-
//! @tparam T type of object to allocate
2814
//! @tparam alignment alignment boundary
15+
//! @tparam T type of object to allocate
2916
//!
3017
//! AlignedAllocator is an implementation of the C++ Allocator concept for use with standard library containers.
3118
//!
32-
template <typename T, std::size_t alignment>
19+
template <std::size_t alignment, typename T = std::byte>
3320
struct AlignedAllocator
3421
{
35-
typedef T* pointer;
36-
typedef T& reference;
37-
typedef T const* const_pointer;
38-
typedef T const& const_reference;
39-
typedef T value_type;
40-
typedef std::size_t size_type;
41-
typedef std::ptrdiff_t difference_type;
22+
using value_type = T;
4223

43-
template <typename U>
44-
struct rebind { typedef AlignedAllocator<U, alignment> other; };
45-
46-
AlignedAllocator ()
47-
{}
24+
AlignedAllocator () = default;
4825

4926
template <typename U>
50-
AlignedAllocator (AlignedAllocator<U, alignment>&)
27+
constexpr AlignedAllocator (AlignedAllocator<alignment, U> const&) noexcept
5128
{}
5229

53-
pointer address (reference x) const
30+
[[nodiscard]] T* allocate (std::size_t n)
5431
{
55-
return &x;
56-
}
32+
if (n > std::numeric_limits<std::size_t>::max () / sizeof (T))
33+
throw std::bad_array_new_length {};
5734

58-
const_pointer address (const_reference x) const
59-
{
60-
return &x;
61-
}
62-
63-
pointer allocate (size_type n, typename AlignedAllocator<void, alignment>::pointer = nullptr)
64-
{
65-
void* ptr = visual_mem_malloc_aligned (n * sizeof (T), alignment);
35+
auto ptr = visual_mem_malloc_aligned (n * sizeof (T), alignment);
6636

6737
if (!ptr)
68-
throw std::bad_alloc ();
38+
throw std::bad_alloc {};
6939

70-
return pointer (ptr);
40+
return static_cast<T*> (ptr);
7141
}
7242

73-
void deallocate (pointer ptr, size_type) noexcept
43+
void deallocate (T* ptr, std::size_t) noexcept
7444
{
7545
visual_mem_free_aligned (ptr);
7646
}
77-
78-
size_type max_size () const
79-
{
80-
return size_type (-1) / sizeof (T);
81-
}
82-
83-
void construct (pointer p, const_reference x)
84-
{
85-
new (p) T (x);
86-
}
87-
88-
void destroy (pointer p)
89-
{
90-
p->~T ();
91-
}
9247
};
9348

9449
template <typename T, typename U, std::size_t alignment>
95-
bool operator== (AlignedAllocator<T, alignment> const&, AlignedAllocator<U, alignment> const&)
50+
bool operator== (AlignedAllocator<alignment, T> const&, AlignedAllocator<alignment, U> const&)
9651
{
9752
return true;
9853
}
9954

10055
template <typename T, typename U, std::size_t alignment>
101-
bool operator!= (AlignedAllocator<T, alignment> const&, AlignedAllocator<U, alignment> const&)
56+
bool operator!= (AlignedAllocator<alignment, T> const&, AlignedAllocator<alignment, U> const&)
10257
{
10358
return false;
10459
}

libvisual/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ INCLUDE_DIRECTORIES(
55
)
66

77
ADD_SUBDIRECTORY(audio_test)
8+
ADD_SUBDIRECTORY(mem_test)
89
ADD_SUBDIRECTORY(video_test)
910
ADD_SUBDIRECTORY(time_test)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
LV_BUILD_TEST(aligned_allocation_test
2+
SOURCES aligned_allocation_test.cpp
3+
)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#include "test.h"
2+
#include <libvisual/libvisual.h>
3+
#include <libvisual/lv_aligned_allocator.hpp>
4+
#include <string>
5+
#include <vector>
6+
#include <cstdint>
7+
8+
namespace
9+
{
10+
inline bool ptr_is_aligned (void* ptr, std::size_t alignment)
11+
{
12+
return (reinterpret_cast<std::intptr_t> (ptr) % alignment) == 0;
13+
}
14+
15+
void test_allocation ()
16+
{
17+
std::array<std::size_t, 6> constexpr alignments { 4, 8, 16, 32, 64, 128 };
18+
19+
for (auto alignment = alignments.begin (); alignment != alignments.end(); ++alignment) {
20+
std::size_t const test_block_size = *alignment * 2 + 1;
21+
22+
void* ptr = visual_mem_malloc_aligned (test_block_size, *alignment);
23+
LV_TEST_ASSERT (ptr_is_aligned (ptr, *alignment));
24+
25+
visual_mem_free_aligned (ptr);
26+
}
27+
}
28+
29+
template <std::size_t alignment>
30+
void test_cxx_allocator ()
31+
{
32+
constexpr size_t test_count = 3;
33+
34+
LV::AlignedAllocator<alignment, std::string> allocator;
35+
using allocator_traits = std::allocator_traits<decltype(allocator)>;
36+
37+
std::string* strings = allocator_traits::allocate (allocator, test_count);
38+
39+
LV_TEST_ASSERT (ptr_is_aligned (strings, alignment));
40+
41+
allocator_traits::deallocate (allocator, strings, test_count);
42+
}
43+
44+
void test_cxx_allocators ()
45+
{
46+
test_cxx_allocator<4> ();
47+
test_cxx_allocator<8> ();
48+
test_cxx_allocator<16> ();
49+
test_cxx_allocator<32> ();
50+
test_cxx_allocator<64> ();
51+
test_cxx_allocator<128> ();
52+
}
53+
}
54+
55+
int main (int argc, char* argv[])
56+
{
57+
LV::System::init (argc, argv);
58+
59+
test_allocation ();
60+
test_cxx_allocators ();
61+
62+
LV::System::destroy ();
63+
}

0 commit comments

Comments
 (0)