can now call operators using paramater order in allocator

thread
Brett 2024-06-06 00:50:44 -04:00
parent 4d731b074d
commit fc8133376d
3 changed files with 141 additions and 71 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(blt-gp VERSION 0.0.13) project(blt-gp VERSION 0.0.14)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)

View File

@ -312,12 +312,16 @@ int main()
alloc.push(50); alloc.push(50);
alloc.push(550.3f); alloc.push(550.3f);
alloc.push(20.1230345); alloc.push(20.1230345);
alloc.push(true);
alloc.push(false);
alloc.push(std::string("SillyString")); alloc.push(std::string("SillyString"));
alloc.push(&"SillyString"); alloc.push(&"SillyString");
std::cout << std::endl; std::cout << std::endl;
std::cout << *alloc.pop<decltype(&"SillString")>() << std::endl; std::cout << *alloc.pop<decltype(&"SillString")>() << std::endl;
std::cout << alloc.pop<std::string>() << std::endl; std::cout << alloc.pop<std::string>() << std::endl;
std::cout << alloc.pop<bool>() << std::endl;
std::cout << alloc.pop<bool>() << std::endl;
std::cout << alloc.pop<double>() << std::endl; std::cout << alloc.pop<double>() << std::endl;
std::cout << alloc.pop<float>() << std::endl; std::cout << alloc.pop<float>() << std::endl;
std::cout << alloc.pop<int>() << std::endl; std::cout << alloc.pop<int>() << std::endl;
@ -331,20 +335,46 @@ int main()
alloc.push(large{}); alloc.push(large{});
std::cout << std::endl; std::cout << std::endl;
std::cout << "Is empty? " << alloc.empty() << std::endl;
alloc.pop<large>(); alloc.pop<large>();
std::cout << "Is empty? " << alloc.empty() << std::endl;
std::cout << alloc.pop<silly>() << std::endl; std::cout << alloc.pop<silly>() << std::endl;
std::cout << "Is empty? " << alloc.empty() << std::endl;
alloc.pop<super_large>(); alloc.pop<super_large>();
std::cout << "Is empty? " << alloc.empty() << std::endl;
alloc.pop<large>(); alloc.pop<large>();
std::cout << "Is empty? " << alloc.empty() << std::endl;
std::cout << alloc.pop<silly>() << std::endl; std::cout << alloc.pop<silly>() << std::endl;
std::cout << std::endl;
std::cout << "Is empty? " << alloc.empty() << " bytes left: " << alloc.bytes_in_head() << std::endl;
std::cout << std::endl;
alloc.push(silly{2, 5});
alloc.push(large{});
alloc.push(super_large{});
alloc.push(silly{80, 10});
alloc.push(large{});
alloc.push(50);
alloc.push(550.3f);
alloc.push(20.1230345);
alloc.push(std::string("SillyString"));
alloc.push(33.22f);
alloc.push(120);
alloc.push(true);
blt::gp::operation<float, float, int, bool> silly_op([](float f, int i, bool b) -> float {
std::cout << "We found values: " << f << " " << i << " " << b << std::endl;
return f + static_cast<float>(i * b);
});
std::cout << alloc.run(silly_op) << std::endl;
std::cout << std::endl;
blt::size_t remaining_bytes = 4096;
//auto* pointer = static_cast<void*>(head->metadata.offset); //auto* pointer = static_cast<void*>(head->metadata.offset);
//return std::align(alignment, bytes, pointer, remaining_bytes); //return std::align(alignment, bytes, pointer, remaining_bytes);
blt::gp::operation<float, float, int, bool> silly([](float f, int i, bool b) -> float {
return static_cast<float>(f);
});
float f = 10.5; float f = 10.5;
int i = 412; int i = 412;
bool b = true; bool b = true;
@ -353,7 +383,7 @@ int main()
blt::span<void*, 3> spv{arr}; blt::span<void*, 3> spv{arr};
std::cout << silly.operator()(spv) << std::endl; std::cout << silly_op.operator()(spv) << std::endl;
std::cout << "Hello World!" << std::endl; std::cout << "Hello World!" << std::endl;
} }

View File

@ -29,6 +29,7 @@
#include <string_view> #include <string_view>
#include <string> #include <string>
#include <utility> #include <utility>
#include <iostream>
namespace blt::gp namespace blt::gp
{ {
@ -85,6 +86,65 @@ namespace blt::gp
std::vector<type> types; std::vector<type> types;
}; };
template<typename Return, typename... Args>
class operation
{
public:
using function_t = std::function<Return(Args...)>;
operation(const operation& copy) = default;
operation(operation&& move) = default;
template<typename T, std::enable_if_t<std::is_same_v<T, function_t>, void>>
explicit operation(const T& functor): func(functor)
{}
template<typename T, std::enable_if_t<!std::is_same_v<T, function_t>, void>>
explicit operation(const T& functor)
{
func = [&functor](Args... args) {
return functor(args...);
};
}
explicit operation(function_t&& functor): func(std::move(functor))
{}
[[nodiscard]] inline Return operator()(Args... args) const
{
return func(args...);
}
Return operator()(blt::span<void*> args)
{
auto pack_sequence = std::make_integer_sequence<blt::u64, sizeof...(Args)>();
return function_evaluator(args, pack_sequence);
}
std::function<Return(blt::span<void*>)> to_functor()
{
return [this](blt::span<void*> args) {
return this->operator()(args);
};
}
private:
template<typename T, blt::size_t index>
static inline T& access_pack_index(blt::span<void*> args)
{
return *reinterpret_cast<T*>(args[index]);
}
template<typename T, T... indexes>
Return function_evaluator(blt::span<void*> args, std::integer_sequence<T, indexes...>)
{
return func(access_pack_index<Args, indexes>(args)...);
}
function_t func;
};
class stack_allocator class stack_allocator
{ {
constexpr static blt::size_t PAGE_SIZE = 0x1000; constexpr static blt::size_t PAGE_SIZE = 0x1000;
@ -99,17 +159,17 @@ namespace blt::gp
void push(T&& value) void push(T&& value)
{ {
auto ptr = allocate_bytes<T>(); auto ptr = allocate_bytes<T>();
head->metadata.offset = static_cast<blt::u8*>(ptr) + sizeof(T); head->metadata.offset = static_cast<blt::u8*>(ptr) + aligned_size<T>();
new(ptr) T(std::forward<T>(value)); new(ptr) T(std::forward<T>(value));
} }
template<typename T> template<typename T>
T pop() T pop()
{ {
constexpr auto TYPE_SIZE = aligned_size<T>(); constexpr static auto TYPE_SIZE = aligned_size<T>();
if (head == nullptr) if (head == nullptr)
throw std::runtime_error("Silly boi the stack is empty!"); throw std::runtime_error("Silly boi the stack is empty!");
if (head->used_bytes_in_block() < static_cast<blt::ptrdiff_t>(sizeof(T))) if (head->used_bytes_in_block() < static_cast<blt::ptrdiff_t>(aligned_size<T>()))
throw std::runtime_error((std::string("Mismatched Types! Not enough space left in block! Bytes: ") += std::to_string( throw std::runtime_error((std::string("Mismatched Types! Not enough space left in block! Bytes: ") += std::to_string(
head->used_bytes_in_block()) += " Size: " + std::to_string(sizeof(T))).c_str()); head->used_bytes_in_block()) += " Size: " + std::to_string(sizeof(T))).c_str());
T t = *reinterpret_cast<T*>(head->metadata.offset - TYPE_SIZE); T t = *reinterpret_cast<T*>(head->metadata.offset - TYPE_SIZE);
@ -126,7 +186,7 @@ namespace blt::gp
template<typename T> template<typename T>
T& from(blt::size_t bytes) T& from(blt::size_t bytes)
{ {
constexpr auto TYPE_SIZE = aligned_size<T>(); constexpr static auto TYPE_SIZE = aligned_size<T>();
auto remaining_bytes = static_cast<blt::i64>(bytes); auto remaining_bytes = static_cast<blt::i64>(bytes);
blt::i64 bytes_into_block = 0; blt::i64 bytes_into_block = 0;
block* blk = head; block* blk = head;
@ -145,9 +205,41 @@ namespace blt::gp
} }
if (blk == nullptr) if (blk == nullptr)
throw std::runtime_error("Some nonsense is going on. This function already smells"); throw std::runtime_error("Some nonsense is going on. This function already smells");
if (blk->used_bytes_in_block() < static_cast<blt::ptrdiff_t>(aligned_size<T>()))
throw std::runtime_error((std::string("Mismatched Types! Not enough space left in block! Bytes: ") += std::to_string(
blk->used_bytes_in_block()) += " Size: " + std::to_string(sizeof(T))).c_str());
return *reinterpret_cast<T*>((blk->metadata.offset - bytes_into_block) - TYPE_SIZE); return *reinterpret_cast<T*>((blk->metadata.offset - bytes_into_block) - TYPE_SIZE);
} }
template<blt::u64 index, typename... Args>
blt::size_t getByteOffset()
{
blt::size_t offset = 0;
blt::size_t current_index = 0;
((offset += (current_index++ > index ? aligned_size<Args>() : 0)), ...);
return offset;
}
template<typename CurrentArgument, blt::u64 index, typename... Args>
CurrentArgument& getArgument()
{
auto bytes = getByteOffset<index, Args...>();
return from<CurrentArgument>(bytes);
}
template<typename Return, typename... Args, blt::u64... indices>
Return sequence_to_indices(const operation<Return, Args...>& function, std::integer_sequence<blt::u64, indices...>)
{
return function(getArgument<Args, indices, Args...>()...);
}
template<typename Return, typename... Args>
Return run(const operation<Return, Args...>& function)
{
auto seq = std::make_integer_sequence<blt::u64, sizeof...(Args)>();
return sequence_to_indices(function, seq);
}
[[nodiscard]] bool empty() const [[nodiscard]] bool empty() const
{ {
if (head == nullptr) if (head == nullptr)
@ -157,6 +249,13 @@ namespace blt::gp
return head->used_bytes_in_block() == 0; return head->used_bytes_in_block() == 0;
} }
[[nodiscard]] blt::ptrdiff_t bytes_in_head() const
{
if (head == nullptr)
return 0;
return head->used_bytes_in_block();
}
stack_allocator() = default; stack_allocator() = default;
stack_allocator(const stack_allocator& copy) = delete; stack_allocator(const stack_allocator& copy) = delete;
@ -278,72 +377,13 @@ namespace blt::gp
template<typename T> template<typename T>
static inline constexpr blt::size_t aligned_size() noexcept static inline constexpr blt::size_t aligned_size() noexcept
{ {
return (sizeof(T) + (MAX_ALIGNMENT - 1)) & ~(MAX_ALIGNMENT-1); return (sizeof(T) + (MAX_ALIGNMENT - 1)) & ~(MAX_ALIGNMENT - 1);
} }
private: private:
block* head = nullptr; block* head = nullptr;
}; };
template<typename Return, typename... Args>
class operation
{
public:
using function_t = std::function<Return(Args...)>;
operation(const operation& copy) = default;
operation(operation&& move) = default;
template<typename T, std::enable_if_t<std::is_same_v<T, function_t>, void>>
explicit operation(const T& functor): func(functor)
{}
template<typename T, std::enable_if_t<!std::is_same_v<T, function_t>, void>>
explicit operation(const T& functor)
{
func = [&functor](Args... args) {
return functor(args...);
};
}
explicit operation(function_t&& functor): func(std::move(functor))
{}
inline Return operator()(Args... args)
{
return func(args...);
}
Return operator()(blt::span<void*> args)
{
auto pack_sequence = std::make_integer_sequence<blt::u64, sizeof...(Args)>();
return function_evaluator(args, pack_sequence);
}
std::function<Return(blt::span<void*>)> to_functor()
{
return [this](blt::span<void*> args) {
return this->operator()(args);
};
}
private:
template<typename T, blt::size_t index>
static inline T& access_pack_index(blt::span<void*> args)
{
return *reinterpret_cast<T*>(args[index]);
}
template<typename T, T... indexes>
Return function_evaluator(blt::span<void*> args, std::integer_sequence<T, indexes...>)
{
return func(access_pack_index<Args, indexes>(args)...);
}
function_t func;
};
} }