diff --git a/src/lib/several-builder.hpp b/src/lib/several-builder.hpp index 8c3309a0e..ce5d69946 100644 --- a/src/lib/several-builder.hpp +++ b/src/lib/several-builder.hpp @@ -74,11 +74,12 @@ namespace lib { template class ALO> - struct ElementFactory + class ElementFactory : private ALO { using Allo = ALO; using AlloT = std::allocator_traits; + using Bucket = ArrayBucket; Allo& baseAllocator() { return *this; } @@ -93,10 +94,48 @@ namespace lib { return XAllo{}; } + static size_t + calcSize (size_t cnt, size_t spread) + { + return sizeof(Bucket) - sizeof(Bucket::storage) + + cnt * spread; + } + + public: ElementFactory (Allo allo = Allo{}) : Allo{std::move (allo)} { } + Bucket* + create (size_t cnt, size_t spread) + { + size_t storageBytes = calcSize (cnt, spread); + std::byte* loc = AlloT::allocate (baseAllocator(), storageBytes); + + using BucketAlloT = typename AlloT::template rebind_traits; + auto bucketAllo = adaptAllocator(); + try { BucketAlloT::construct (bucketAllo, loc, spread); } + catch(...) + { + AlloT::deallocate (baseAllocator(), loc, storageBytes); + throw; + } + return static_cast (loc); + }; + + template + E& + createAt (Bucket* bucket, size_t idx, ARGS&& ...args) + { + REQUIRE (bucket); + using ElmAlloT = typename AlloT::template rebind_traits; + auto elmAllo = adaptAllocator(); + E* loc = & bucket->subscript (idx); + ElmAlloT::construct (elmAllo, loc, forward (args)...); + ENSURE (loc); + return *loc; + }; + template void destroy (ArrayBucket* bucket, size_t size) @@ -107,9 +146,7 @@ namespace lib { for (size_t i=0; isubscript(i)); - size_t storageBytes = sizeof(ArrayBucket) - sizeof(ArrayBucket::storage) - + size * bucket->spread; - + size_t storageBytes = calcSize (size, bucket->spread); AlloT::deallocate (baseAllocator(), bucket, storageBytes); }; }; diff --git a/src/lib/several.hpp b/src/lib/several.hpp index 7da706306..cbe84be5b 100644 --- a/src/lib/several.hpp +++ b/src/lib/several.hpp @@ -48,15 +48,14 @@ namespace lib { template struct ArrayBucket { - union Manager - { - typedef void (*Deleter) (ArrayBucket*, size_t); - - bool unmanaged :1; - Deleter deleter; - }; + ArrayBucket (size_t elmSize = sizeof(I)) + : deleter{nullptr} + , spread{elmSize} + { } - Manager manager; + typedef void (*Deleter) (ArrayBucket*, size_t); + + Deleter deleter; size_t spread; /** mark start of the storage area */ @@ -145,8 +144,8 @@ namespace lib { void discardData() { - if (data_ and data_->manager.deleter) - (*data_->manager.deleter) (data_, size_); + if (data_ and data_->deleter) + (*data_->deleter) (data_, size_); } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 6d8fab0e4..00d8c45cb 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -81952,9 +81952,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + @@ -81975,10 +81975,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + + + + + @@ -82256,10 +82260,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - + +