better emplace implementation

This commit is contained in:
Richard Thier 2024-08-30 13:34:06 +02:00
parent 853f301b0f
commit 39a7d8effe

View File

@ -29,7 +29,7 @@ class TurboList {
uint32_t capacity; uint32_t capacity;
TL_NOINLINE void grow_and_insert(T elem) noexcept { TL_NOINLINE T& grow_and_insert(T elem) noexcept {
// assert(mid == 0); // assert(mid == 0);
if(old) FREE(old); if(old) FREE(old);
old = nex; old = nex;
@ -38,7 +38,7 @@ class TurboList {
nex = (int *) MALLOC(this->capacity * sizeof(T)); nex = (int *) MALLOC(this->capacity * sizeof(T));
// Will go into the INSERT code path here // Will go into the INSERT code path here
insert(elem); return insert(elem);
} }
public: public:
@ -72,7 +72,7 @@ public:
} }
} }
inline void insert(T elem) noexcept { inline T& insert(T elem) noexcept {
if(TL_LIKELY(end < capacity)) { if(TL_LIKELY(end < capacity)) {
// INSERT // INSERT
@ -87,17 +87,43 @@ public:
mid -= hasmid; mid -= hasmid;
nex[mid] = hasmid ? old[mid] : nex[mid]; nex[mid] = hasmid ? old[mid] : nex[mid];
nex[end++] = elem; return (nex[end++] = elem);
} else { } else {
// GROW // GROW
grow_and_insert(elem); return grow_and_insert(elem);
} }
} }
template<typename... Args> template<typename... Args>
inline void emplace(Args&&... args) { inline T& emplace(Args&&... args) {
// FIXME: placement new needed if(TL_LIKELY(end < capacity)) {
insert(T(std::forward<Args>(args)...));
// 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>(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>(args)...));
}
} }
inline uint32_t size() noexcept { inline uint32_t size() noexcept {