diff --git a/src/lib/allocator-handle.hpp b/src/lib/allocator-handle.hpp index 5526baa1c..46b900c51 100644 --- a/src/lib/allocator-handle.hpp +++ b/src/lib/allocator-handle.hpp @@ -64,12 +64,139 @@ namespace lib { + namespace allo { /** Concepts and Adapter for custom memory management */ + + /////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1366 : define Allocator Concepts here + /// TODO the following Concepts can be expected here (with C++20) + /// - Allocator : for the bare memory allocation + /// - Factory : for object fabrication and disposal + /// - Handle : a functor front-end to be dependency-injected + + + /** + * Adapter to implement the *Factory* concept based on a `std::allocator` + * @tparam ALO a std::allocator instance or anything compliant to [Allocator] + * [Allocator]: https://en.cppreference.com/w/cpp/named_req/Allocator + * @note in addition to the abilities defined by the standard, this adapter + * strives to provide some kind of _lateral leeway,_ attempting to + * create dedicated allocators for other types than the BaseType + * implied by the given \a ALO (standard-allocator). + * - this is possible if the rebound allocator can be constructed + * from the given base allocator + * - alternatively, an attempt will be made to default-construct + * the rebound allocator for the other type requested. + * @warn Both avenues for adaptation may fail, which could lead to + * compilation or runtime failures. + */ + template + class StdFactory + { + using Allo = ALO; + using AlloT = std::allocator_traits; + using BaseType = typename Allo::value_type; + + Allo allocator_; + + template + auto + adaptAllocator (Allo const& baseAllocator) + { + using XAllo = typename AlloT::template rebind_alloc; + if constexpr (std::is_constructible_v) + return XAllo(allocator_); + else + return XAllo(); + } + + template + typename ALOT::pointer + construct (typename ALOT::alocator_type& allo, ARGS&& ...args) + { + auto loc = ALOT::allocate (allocator_, 1); + ALOT::construct (allocator_, loc, std::forward(args)...); + return loc; + } + + template + void + destroy (typename ALOT::alocator_type& allo, typename ALOT::pointer elm) + { + ALOT::destroy (allo, elm); + ALOT::deallocate (allo, elm, 1); + } + + + public: + /** + * Create an instance of the adapter factory, + * forwarding to the embedded standard conforming allocator + * for object creation and destruction and memory management. + * @param allo (optional) instance of the C++ standard allocator + * used for delegation, will be default constructed if omitted. + * @remark the adapted standard allocator is assumed to be either a copyable + * value object, or even a mono-state; in both cases, a dedicated + * manager instance residing »elsewhere« is referred, rendering + * all those front-end instances exchangeable. + */ + StdFactory (Allo allo = Allo{}) + : allocator_{std::move (allo)} + { } + + template + bool constexpr operator== (StdFactory const& o) const + { + return allocator_ == o.allocator_; + } + template + bool constexpr operator!= (StdFactory const& o) const + { + return not (allocator_ == o.allocator_); + } + + + /** create new element using the embedded allocator */ + template + TY* + create (ARGS&& ...args) + { + if constexpr (std::is_same_v) + { + return construct (allocator_, std::forward(args)...); + } + else + { + using XAlloT = typename AlloT::template rebind_traits; + auto xAllo = adaptAllocator (allocator_); + return construct (xAllo, std::forward(args)...); + } + } + + /** destroy the given element and discard the associated memory */ + template + void + dispose (TY* elm) + { + if constexpr (std::is_same_v) + { + destroy (allocator_, elm); + } + else + { + using XAlloT = typename AlloT::template rebind_traits; + auto xAllo = adaptAllocator (allocator_); + destroy (xAllo, elm); + } + } + }; + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1366 : the following code becomes obsolete in the long term + /** * Placeholder implementation for a custom allocator * @todo shall be replaced by an AllocationCluster eventually - * @note conforming to a prospective C++20 Concept `Allo` + * @todo 5/2024 to be reworked and aligned with a prospective C++20 Allocator Concept /////////////////////TICKET #1366 * @remark using `std::list` container, since re-entrant allocation calls are possible, * meaning that further allocations will be requested recursively from a ctor. * Moreover, for the same reason we separate the allocation from the ctor call, @@ -98,7 +225,7 @@ namespace lib { return * std::launder (reinterpret_cast (&buf_)); } void - discard() /// @warning strong assumption made here: Payload was created + discard() /// @warning strong assumption made here: Payload was created { access().~TY(); } diff --git a/src/lib/linked-elements.hpp b/src/lib/linked-elements.hpp index 00985340a..de7a6459c 100644 --- a/src/lib/linked-elements.hpp +++ b/src/lib/linked-elements.hpp @@ -63,6 +63,7 @@ #include "lib/error.hpp" #include "lib/nocopy.hpp" #include "lib/iter-adapter.hpp" +#include "lib/allocator-handle.hpp" #include "lib/util.hpp" #include @@ -110,83 +111,6 @@ namespace lib { } }; - template - struct OwningAlloc - : util::MoveOnly - { - using Allo = ALO; - using AlloT = std::allocator_traits; - using BaseType = typename Allo::value_type; - - Allo allocator_; - - OwningAlloc (Allo allo = Allo{}) - : allocator_{allo} - { } - - template - auto - adaptAllocator (Allo const& baseAllocator) - { - using XAllo = typename AlloT::template rebind_alloc; - if constexpr (std::is_constructible_v) - return XAllo(allocator_); - else - return XAllo(); - } - - template - auto& - construct (typename ALOT::alocator_type& allo, ARGS&& ...args) - { - auto loc = ALOT::allocate (allocator_, 1); - ALOT::construct (allocator_, loc, std::forward(args)...); - return *loc; - } - - template - void - destroy (typename ALOT::alocator_type& allo, typename ALOT::pointer elm) - { - ALOT::destroy (allo, elm); - ALOT::deallocate (allo, elm, 1); - } - - - /** create new element using the embedded allocator */ - template - TY& - create (ARGS&& ...args) - { - if constexpr (std::is_same_v) - { - return construct (allocator_, std::forward(args)...); - } - else - { - using XAlloT = typename AlloT::template rebind_traits; - auto xAllo = adaptAllocator (allocator_); - return construct (xAllo, std::forward(args)...); - } - } - - template - void - destroy (TY* elm) - { - if constexpr (std::is_same_v) - { - destroy (allocator_, elm); - } - else - { - using XAlloT = typename AlloT::template rebind_traits; - auto xAllo = adaptAllocator (allocator_); - destroy (xAllo, elm); - } - } - - }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 485498827..bc3f8bca3 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -64879,13 +64879,63 @@ - - + + + + + + + + +

+ nach Alexandrescu: sollte composable sein +

+ +
+ +
+
+ + + + + +

+ kann Objekte beliebigen Typs erzeugen und verwerfen +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + - + + + + - + + @@ -64918,8 +64968,135 @@ - - + + + + + + +

+ Namespace: lib::allo +

+ +
+
+ + + + +

+ die Grundbegriffe sind für Concepts reserviert +

+ + +
+ + + + + + + + + +

+ wenngleich auch der Vortrag relativ viel Geplänkel enthält, so ergibt sich doch insgesamt eine Sicht auf die Design-Erfahrungen der letzten 15 Jahre, und die daraus ableitbaren Strukturen erscheinen mir ausgereifter als die Strukturen aus dem C++ - Standard +

+ +
+ + + + + + + + + + + + + + + + + + +

+ Hier wird wahrscheinlich ein komplexes Subsystem aus Metaprogrammierung entstehen. Die verschiedensten praktischen Varianten sind denkbar und auch valide +

+
    +
  • + die Factory kann sich selbst erzeugen, indem sie auf einen Monostate zurückgreift. Das ist in der Praxis der wichtigste Fall, der im Besonderen für die normale Heap-Allokation gilt, aber auch Thread-Local und damit Kontext-Bezogen auslegbar ist. +
  • +
  • + es könnte nur Copy-Construction oder Delegation erlaubt sein, und die Factory ist in diesem Fall nur ein Front-End-Handle +
  • +
  • + man könnte einen Konstruktor bieten, der einen C++-Standard-Allokator akzeptiert und adaptiert +
  • +
+ + +
+
+
+ + + + +

+ Factory wird das zentrale Schnittstellen-Concept zur restlichen Applikation +

+ + +
+
+
+ + + + + + + + + + + + +

+ Präfix Std +

+ +
+ + + + + + + + + +
+
+ + + + + + + + + + + + + + + + @@ -64996,10 +65173,17 @@ + + + + + + + @@ -81257,7 +81441,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + @@ -82231,9 +82417,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ -