Created
August 26, 2023 00:25
-
-
Save Andersama/bea7424070b1b61602e14e2c573365e3 to your computer and use it in GitHub Desktop.
Incomplete struct of arrays module file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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