Skip to content

Commit

Permalink
Add StackAllocator (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
jatinchowdhury18 authored Aug 9, 2023
1 parent f20e742 commit bb8daf0
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#pragma once

#include <vector>

namespace chowdsp
{
/** A simple stack allocator */
class StackAllocator
{
public:
StackAllocator() = default;

StackAllocator (const StackAllocator&) = delete;
StackAllocator& operator= (const StackAllocator&) = delete;

StackAllocator (StackAllocator&&) noexcept = default;
StackAllocator& operator= (StackAllocator&&) noexcept = default;

/** Re-allocates the internal buffer with a given number of bytes */
void reset (size_t new_size_bytes)
{
clear();
raw_data.resize (new_size_bytes, {});
}

/** Resets the allocator */
void clear() noexcept
{
bytes_used = 0;
}

/** Returns the number of bytes currently being used */
[[nodiscard]] size_t get_bytes_used() const noexcept { return bytes_used; }

/** Allocates a given number of bytes */
void* allocate_bytes (size_t num_bytes) noexcept
{
if (bytes_used + num_bytes > raw_data.size())
return nullptr;

auto* pointer = raw_data.data() + bytes_used;
bytes_used += num_bytes;
return pointer;
}

/** Allocates space for some number of objects of type T */
template <typename T, typename IntType>
T* allocate (IntType num_Ts) noexcept
{
return static_cast<T*> (allocate_bytes ((size_t) num_Ts * sizeof (T)));
}

/** Returns a pointer to the internal buffer with a given offset in bytes */
template <typename T, typename IntType>
T* data (IntType offset_bytes) noexcept
{
return reinterpret_cast<T*> (raw_data.data() + offset_bytes);
}

/**
* Creates a "frame" for the allocator.
* Once the frame goes out of scope, the allocator will be reset
* to whatever it's state was at the beginning of the frame.
*/
struct StackAllocatorFrame
{
explicit StackAllocatorFrame (StackAllocator& allocator)
: alloc (allocator),
bytes_used_at_start (alloc.bytes_used)
{
}

~StackAllocatorFrame()
{
alloc.bytes_used = bytes_used_at_start;
}

StackAllocator& alloc;
const size_t bytes_used_at_start;
};

private:
std::vector<std::byte> raw_data {};
size_t bytes_used = 0;
};
} // namespace chowdsp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ BEGIN_JUCE_MODULE_DECLARATION
#include "Structures/chowdsp_OptionalPointer.h"
#include "Structures/chowdsp_RawObject.h"
#include "Structures/chowdsp_SmallVector.h"
#include "Structures/chowdsp_StackAllocator.h"
#include "Structures/chowdsp_StringLiteral.h"

#include "Helpers/chowdsp_Iterators.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ target_sources(chowdsp_data_structures_test
LocalPointerTest.cpp
OptionalPointerTest.cpp
SmallVectorTest.cpp
StackAllocatorTest.cpp
StringLiteralTest.cpp
TupleHelpersTest.cpp
VectorHelpersTest.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <CatchUtils.h>
#include <chowdsp_data_structures/chowdsp_data_structures.h>

TEST_CASE ("Stack Allocator Test", "[common][data-structures]")
{
chowdsp::StackAllocator allocator;
allocator.reset (150);

// allocate doubles
{
auto* some_doubles = allocator.allocate<double> (10);
REQUIRE ((void*) some_doubles == allocator.data<void> (0));
REQUIRE (allocator.get_bytes_used() == 80);
}

// allocate ints
{
auto* some_ints = allocator.allocate<int32_t> (10);
REQUIRE ((void*) some_ints == allocator.data<void> (80));
REQUIRE (allocator.get_bytes_used() == 120);
}

// allocate with stack frame
{
chowdsp::StackAllocator::StackAllocatorFrame frame { allocator };
auto* some_chars = allocator.allocate<char> (30);
juce::ignoreUnused (some_chars);
REQUIRE (allocator.get_bytes_used() == 150);
}

REQUIRE (allocator.get_bytes_used() == 120);

// overfull allocation
REQUIRE (allocator.allocate<double> (100) == nullptr);

// clear allocator
allocator.clear();
REQUIRE (allocator.get_bytes_used() == 0);
}

0 comments on commit bb8daf0

Please sign in to comment.