Last active
August 21, 2020 13:14
-
-
Save yuyoyuppe/3544624777c0800c5884aa887774edfc to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#include <array> | |
#include <vector> | |
#include <memory_resource> | |
#include <iostream> | |
int main() | |
{ | |
std::array<char, 24> memory{}; | |
std::pmr::monotonic_buffer_resource arena{data(memory), size(memory), nullptr}; | |
std::pmr::vector<char> v(8, 'A', &arena); | |
auto print_state = [&]{ | |
std::cout << "memory: "; | |
for(const char c : memory) std::cout << '\'' << c << "' "; | |
std::cout << '\n'; | |
std::cout << "vector [" << size(v) << "]: "; | |
for(const char c : v) std::cout << '\'' << c << "' "; | |
std::cout << '\n' << '\n'; | |
}; | |
print_state(); | |
v.clear(); | |
print_state(); | |
v.assign(8, 'B'); | |
print_state(); | |
//v.assign(9, 'B'); // will crash, since arena has `nullptr` as an upstream resource, and we don't have space in arena for 9 chars | |
return 0; | |
} |
This file contains hidden or 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
#include <array> | |
#include <memory_resource> | |
#include <iostream> | |
// Make sure we don't call global new/delete | |
void operator delete(void *) { std::cout << "delete called!\n"; } | |
void * operator new(std::size_t) | |
{ | |
std::cout << "new called!\n"; | |
return nullptr; | |
} | |
void * operator new(std::size_t, std::align_val_t) | |
{ | |
std::cout << "new called!\n"; | |
return nullptr; | |
} | |
template <class... Args> | |
constexpr bool all_equal(const Args &... args) | |
{ | |
if constexpr(sizeof...(Args) == 0) | |
{ | |
return true; | |
} | |
else | |
{ | |
return [](const auto & head, const auto &... rest) { return ((head == rest) && ...); }(args...); | |
} | |
} | |
template <typename Interface, typename... Types> | |
class polymorphic_arena_holder | |
{ | |
// TODO: support different alignment type by desc-sorting the objects | |
static_assert(all_equal(alignof(Types)...), "types must have the same alignment!"); | |
static inline void deleter(Interface * const ptr) noexcept { ptr->~Interface(); } | |
using object_ptr_t = std::unique_ptr<Interface, decltype(&deleter)>; | |
static constexpr size_t storage_size = (sizeof(Types) + ...); | |
std::aligned_storage_t<storage_size, alignof(Interface)> _storage; | |
std::pmr::monotonic_buffer_resource _arena; | |
std::array<object_ptr_t, sizeof...(Types)> _objects; | |
public: | |
// TODO: support ctor args | |
polymorphic_arena_holder() | |
: _arena{&_storage, storage_size, std::pmr::null_memory_resource()} | |
, _objects{ | |
object_ptr_t{new(_arena.allocate(sizeof(Types), alignof(Types))) Types{}, deleter}..., | |
} | |
{ | |
} | |
const decltype(_objects) & objects() const { return _objects; } | |
}; | |
struct base | |
{ | |
virtual void go() = 0; | |
virtual ~base(){}; | |
}; | |
struct d1 : base | |
{ | |
virtual void go() override { std::cout << "d1 go!\n"; } | |
~d1() { std::cout << "d1 destroyed\n"; } | |
}; | |
struct d2 : base | |
{ | |
virtual void go() override { std::cout << "d2 go!\n"; } | |
~d2() { std::cout << "d2 destroyed\n"; } | |
}; | |
int main() | |
{ | |
polymorphic_arena_holder<base, d1, d2> holder; | |
for(auto & b : holder.objects()) | |
b->go(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output:
example 1:
example 2: