From 39a7d8effe04921066cded80bdaa0bb1086ac02e Mon Sep 17 00:00:00 2001 From: Richard Thier Date: Fri, 30 Aug 2024 13:34:06 +0200 Subject: [PATCH] better emplace implementation --- TurboList.hpp | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/TurboList.hpp b/TurboList.hpp index 6e53c7e..894066f 100644 --- a/TurboList.hpp +++ b/TurboList.hpp @@ -29,7 +29,7 @@ class TurboList { uint32_t capacity; - TL_NOINLINE void grow_and_insert(T elem) noexcept { + TL_NOINLINE T& grow_and_insert(T elem) noexcept { // assert(mid == 0); if(old) FREE(old); old = nex; @@ -38,7 +38,7 @@ class TurboList { nex = (int *) MALLOC(this->capacity * sizeof(T)); // Will go into the INSERT code path here - insert(elem); + return insert(elem); } public: @@ -72,7 +72,7 @@ public: } } - inline void insert(T elem) noexcept { + inline T& insert(T elem) noexcept { if(TL_LIKELY(end < capacity)) { // INSERT @@ -87,17 +87,43 @@ public: mid -= hasmid; nex[mid] = hasmid ? old[mid] : nex[mid]; - nex[end++] = elem; + return (nex[end++] = elem); } else { // GROW - grow_and_insert(elem); + return grow_and_insert(elem); } } template - inline void emplace(Args&&... args) { - // FIXME: placement new needed - insert(T(std::forward(args)...)); + inline T& emplace(Args&&... args) { + if(TL_LIKELY(end < capacity)) { + + // INSERT + + /* Same as this: + if(mid > 0) { + nex[mid - 1] = old[mid - 1]; + --mid; + } + */ + bool hasmid = (mid > 0); + mid -= hasmid; + nex[mid] = hasmid ? old[mid] : nex[mid]; + + // Placement new + return *new (nex + end++) T(std::forward(args)...); + } else { + // GROW + // + // Rem.: I just chose this to be less optimized than + // it is possible by making a copy and reusing + // the existing grow and insert code instead of + // writing a new "grow_and_emplace" again. + // + // This happens rarely so its probably fine and + // makes less template instantiations, smaller binary. + return grow_and_insert(T(std::forward(args)...)); + } } inline uint32_t size() noexcept {