Skip to content

Instantly share code, notes, and snippets.

@Andersama
Created August 26, 2023 00:25
Show Gist options
  • Save Andersama/bea7424070b1b61602e14e2c573365e3 to your computer and use it in GitHub Desktop.
Save Andersama/bea7424070b1b61602e14e2c573365e3 to your computer and use it in GitHub Desktop.
Incomplete struct of arrays module file
module;
import <array>;
import <vector>;
import <tuple>;
import <bit>;
export module struct_of_arrays;
export {
/*
A barebones struct of arrays base structure
*/
template <typename T>
using ptr_of = T*;
template <typename T>
struct array_slice {
T* ptr = {};
size_t size = {};
};
template <template <typename...> class List,
template <typename> class Mod,
typename... Args>
struct modify {
using type = List<typename Mod<Args>::type...>;
};
template <class Tuple, class F, std::size_t... I>
F for_each_impl(Tuple && tuple, F && f, std::index_sequence<I...>) {
(f(std::get<I>(tuple)), ...);
return f;
}
template <typename... Ts>
struct struct_of_arrays_view {
using idx_sequence = std::make_index_sequence<sizeof...(Ts)>;
using tuple_type = std::tuple<Ts...>;
using ptr_types = std::tuple<ptr_of<Ts>...>;
using slice_type = std::tuple<array_slice<Ts>...>;
static constexpr size_t slice_count = sizeof...(Ts);
union {
slice_type slices = {};
std::array<array_slice<uint8_t>, sizeof...(Ts)> slices_array;
};
template <typename Target, size_t N, typename... List>
constexpr size_t type_index() {
size_t idx = 0;
size_t count = N;
bool found = false;
((
found = found || (std::is_same<Target, List>::value && count == 0),
idx = idx +
(!std::is_same<Target, List>::value && !found) ||
(std::is_same<Target, List>::value && count > 0),
count = count - (std::is_same<Target, List>::value && count > 0)),
...);
return idx;
}
template <size_t N>
constexpr auto get() {
return std::get<N>(slices);
}
template <typename T, size_t N = 0>
constexpr auto get() {
constexpr size_t index = type_index<T, N, Ts...>();
if constexpr (index < sizeof...(Ts)) {
return std::get<index>(slices);
}
else {
return array_slice<uint8_t>{};
}
}
// the allocation pointer
uint8_t* _ptr = nullptr;
size_t _capacity = {};
struct allocation_info {
size_t size = {};
size_t padding = {};
};
constexpr allocation_info quick_allocation_sizing(size_t count) {
allocation_info a;
// overallocates by reserving enough for padding between each type
constexpr size_t type_sizes = ((sizeof(Ts)) + ... + 0);
constexpr size_t type_alignments = ((alignof(Ts)) + ... + 0);
a.size = count * type_sizes + type_alignments;
a.padding = type_alignments;
return a;
}
constexpr allocation_info allocation_sizing(size_t count) {
allocation_info a;
size_t p = 0;
((
p = ((a.size % alignof(Ts)) ? (alignof(Ts) - (a.size % alignof(Ts))) : 0),
a.padding = a.padding + p,
a.size = a.size + p,
a.size = a.size + sizeof(Ts) * count),
...);
return a;
}
template <size_t... Idxs>
constexpr void init(uint8_t* unaligned_ptr, size_t cap, std::index_sequence<Idxs...>) {
allocation_info a = {};
a.size = (uintptr_t)unaligned_ptr;
size_t p = 0;
// optimizer should kick in
size_t previous_alignment = 0;
_capacity = cap;
_ptr = unaligned_ptr;
((
p = (((uintptr_t)(unaligned_ptr + a.size) % alignof(Ts)) && (alignof(Ts) != previous_alignment) ? alignof(Ts) - ((uintptr_t)(unaligned_ptr + a.size) % alignof(Ts)) : 0),
previous_alignment = alignof(Ts),
a.padding = a.padding + p,
a.size = a.size + p,
std::get<Idxs>(slices).ptr = std::bit_cast<decltype(std::get<Idxs>(slices).ptr)>(unaligned_ptr + a.size),
// slices_array[idx].ptr = unaligned_ptr + a.size, // we've aligned the pointer via the padding step (p)
a.size = a.size + sizeof(Ts) * cap, ),
...);
}
constexpr struct_of_arrays_view() = default;
constexpr struct_of_arrays_view(uint8_t* unaligned_ptr, size_t cap) {
init(unaligned_ptr, cap, idx_sequence{});
}
};
//TODO: the rest of this
template <typename Allocator, typename... Ts>
struct struct_of_arrays {
using backing_struct = struct_of_arrays_view<Ts...>;
struct_of_arrays_view<Ts...> soa = {};
constexpr struct_of_arrays() = default;
~struct_of_arrays() {
//
}
// std::vector<uint8_t, Allocator> bytes = {};
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment