stack.storage.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <felspar/memory/stack.storage.hpp>
#include <felspar/test.hpp>

#include <felspar/exceptions.hpp>


namespace {


    auto const suite = felspar::testsuite("stack.storage");

    auto const ga = suite.test("good alloc", [](auto check) {
        felspar::memory::stack_storage<1u << 10, 4u, 8u> stack;

        auto a1 = stack.allocate(8u);
        check(a1) == reinterpret_cast<std::byte const *>(&stack);
        check(stack.free()) == stack.storage_bytes - 8u;

        auto a2 = stack.allocate(1u);
        check(a2) == reinterpret_cast<std::byte const *>(&stack) + 8u;
        check(stack.free()) == stack.storage_bytes - 16u;

        auto a3 = stack.allocate(stack.storage_bytes - 16u);
        check(a3) == reinterpret_cast<std::byte const *>(&stack) + 16u;
    });


    auto const ba = suite.test("bad alloc", [](auto check) {
        felspar::memory::stack_storage<64, 2, 16> stack;

        check([&]() { [[maybe_unused]] auto _ = stack.allocate(65u); })
                .throws(felspar::stdexcept::bad_alloc{
                        "Out of free memory -- memory exhausted"});

        auto a1 = stack.allocate(1u);
        check(a1) == reinterpret_cast<std::byte const *>(&stack);
        check(stack.free()) == stack.storage_bytes - 16u;

        auto a2 = stack.allocate(1u);
        check(a2) == reinterpret_cast<std::byte const *>(&stack) + 16u;
        check(stack.free()) == stack.storage_bytes - 32u;

        check([&]() { [[maybe_unused]] auto _ = stack.allocate(8u); })
                .throws(felspar::stdexcept::bad_alloc{
                        "Out of allocation bookkeeping slots"});
    });


    auto const d = suite.test("deallocate", [](auto check) {
        felspar::memory::stack_storage<64u, 8u, 8u> stack;

        auto a1 = stack.allocate(1u);
        check(a1) == reinterpret_cast<std::byte const *>(&stack);
        auto a2 = stack.allocate(1u);
        check(a2) == reinterpret_cast<std::byte const *>(&stack) + 8u;
        auto a3 = stack.allocate(1u);
        check(a3) == reinterpret_cast<std::byte const *>(&stack) + 16u;

        stack.deallocate(a3, 1u);
        auto a4 = stack.allocate(1u);
        check(a4) == a3;

        stack.deallocate(a1, 1u);
        auto a5 = stack.allocate(1u);
        check(a5) == reinterpret_cast<std::byte const *>(&stack);
        stack.deallocate(a5, 1u);

        stack.deallocate(a2, 1u);
        stack.deallocate(a4, 1u);
        check(stack.free()) == 64u;

        auto a6 = stack.allocate(1u);
        check(a6) == reinterpret_cast<std::byte const *>(&stack);
        stack.deallocate(a6, 1u);
        check(stack.free()) == 64u;
    });


}