New allocator uses global memory
I propose a new allocator that uses global (i.e. static duration) memory. Here's my current experimental code: #include <cstddef> /* size_t */ #include <new> /* Only for bad_alloc */ static int this_translation_unit; /* This serves the same purpose as __FILE__ */ template<typename T, std::size_t t_capacity, std::size_t t_counter, int *t_file = &this_translation_unit> class StaticAllocator { protected: static T buf[t_capacity]; public: typedef T value_type; template<typename U> struct rebind { typedef StaticAllocator<U, t_capacity, t_counter, t_file> other; }; T *allocate(std::size_t const n) { if (n > t_capacity) throw std::bad_alloc(); return buf; } void deallocate(T *, std::size_t) { /* Do Nothing */ } }; template<typename T, std::size_t t_capacity, std::size_t t_counter, int *t_file> T StaticAllocator<T, t_capacity, t_counter, t_file>::buf[t_capacity]; using std::size_t; #include <vector> using std::vector; #include <iostream> using std::cout; using std::endl; auto main(void) -> int { vector< char, StaticAllocator< char, 4, __COUNTER__ > > v; v.push_back('a'); v.push_back('b'); v.push_back('c'); v.push_back('d'); for (auto const &elem : v) cout << elem << endl; vector< char, StaticAllocator< char, 4, __COUNTER__ > > v2; v2.push_back('x'); v2.push_back('y'); v2.push_back('z'); for (auto const &elem : v2) cout << elem << endl; // Now try the first vector again for (auto const &elem : v) cout << elem << endl; } The trick I am using with "this_translation_unit" works fine on GNU and Clang, however it fails to compile on Microsoft because the variable has internal linkage. I'm sure we can do this another way using something from the Boost preprocessor library. The preprocessor macro __COUNTER__ is available on every compiler I know of. Frederick P.S. This is my second idea posted to the Boost dev list. My first one was "istream_iterator_limited".
On 7/01/2020 21:11, Frederick Gotham wrote:
I propose a new allocator that uses global (i.e. static duration) memory.
This looks somewhat like an "arena allocator". You'll find many existing examples using that keyword. When specifically applied to vector, you might also want to look at static_vector: https://www.boost.org/doc/libs/1_72_0/doc/html/boost/container/static_vector...
T *allocate(std::size_t const n) { if (n > t_capacity) throw std::bad_alloc();
return buf; }
Except this is more dangerous than a real arena allocator, since it's single-shot. If the collection tries to make more than one allocation, this will return the same pointer each time, potentially corrupting the data. This makes it incompatible with list-like containers, and possibly risky even with std::vector, depending on how its resize operation is implemented. Using static_vector instead is much safer.
On Thu, 9 Jan 2020 at 16:28, Gavin Lambert via Boost <boost@lists.boost.org> wrote:
On 7/01/2020 21:11, Frederick Gotham wrote:
I propose a new allocator that uses global (i.e. static duration) memory.
This looks somewhat like an "arena allocator". You'll find many existing examples using that keyword.
https://howardhinnant.github.io/stack_alloc.html. Howard has also published: https://howardhinnant.github.io/allocator_boilerplate.html , which makes it a doddle to write your own STL-style allocators (particularly in C++17, as it seems to get simpler as we go along). Using static_vector instead is much safer.
https://github.com/gnzlbg/static_vector is fully constexpr and up for std, AFAIK. Happy New Year to all on the list. degski -- @realdegski https://brave.com/google-gdpr-workaround/ "We value your privacy, click here!" Sod off! - degski "Anyone who believes that exponential growth can go on forever in a finite world is either a madman or an economist" - Kenneth E. Boulding "Growth for the sake of growth is the ideology of the cancer cell" - Edward P. Abbey
participants (3)
-
degski
-
Frederick Gotham
-
Gavin Lambert