Fast af Vector
This commit is contained in:
parent
a9ab6d97fd
commit
a44d2d64a5
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
EngineConfig g_engineConfig {
|
EngineConfig g_engineConfig {
|
||||||
.lighting_enabled = false,
|
.lighting_enabled = true,
|
||||||
|
.version = "0.1.0",
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <string
|
||||||
|
|
||||||
struct EngineConfig {
|
struct EngineConfig {
|
||||||
bool lighting_enabled;
|
bool lighting_enabled;
|
||||||
|
std::string version;
|
||||||
};
|
};
|
||||||
extern EngineConfig g_engineConfig;
|
extern EngineConfig g_engineConfig;
|
||||||
|
@ -1,100 +1,161 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cassert>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cassert>
|
#include <algorithm>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
template<typename T>
|
#ifndef FV_ASSERT
|
||||||
class CreateVector {
|
#define FV_ASSERT(cond) assert(cond)
|
||||||
static_assert(std::is_trivially_destructible_v<T>, "CreateVector only supports trivially destructible types for max performance.");
|
#endif
|
||||||
|
|
||||||
T* data_ = nullptr;
|
template<typename T, size_t SBO_CAP = 16>
|
||||||
|
class FastVector {
|
||||||
|
using StorageT = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
|
||||||
|
|
||||||
|
StorageT sbo_[SBO_CAP];
|
||||||
|
T* data_ = reinterpret_cast<T*>(sbo_);
|
||||||
size_t size_ = 0;
|
size_t size_ = 0;
|
||||||
size_t capacity_ = 0;
|
size_t capacity_ = SBO_CAP;
|
||||||
|
bool heapAllocated_ = false;
|
||||||
|
|
||||||
static constexpr size_t kMinCapacity = 8;
|
inline void reallocate(size_t newCap) {
|
||||||
|
T* newData = reinterpret_cast<T*>(std::malloc(newCap * sizeof(T)));
|
||||||
|
if (!newData) std::abort();
|
||||||
|
|
||||||
inline void grow(size_t minCapacity) {
|
if constexpr (std::is_trivially_copyable_v<T>) {
|
||||||
size_t newCap = capacity_ ? capacity_ * 2 : kMinCapacity;
|
|
||||||
if (newCap < minCapacity) newCap = minCapacity;
|
|
||||||
|
|
||||||
T* newData = (T*)std::malloc(newCap * sizeof(T));
|
|
||||||
if (data_) {
|
|
||||||
std::memcpy(newData, data_, size_ * sizeof(T));
|
std::memcpy(newData, data_, size_ * sizeof(T));
|
||||||
std::free(data_);
|
} else {
|
||||||
|
std::uninitialized_copy(data_, data_ + size_, newData);
|
||||||
|
std::destroy(data_, data_ + size_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (heapAllocated_) std::free(data_);
|
||||||
data_ = newData;
|
data_ = newData;
|
||||||
capacity_ = newCap;
|
capacity_ = newCap;
|
||||||
|
heapAllocated_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline CreateVector() = default;
|
inline FastVector() = default;
|
||||||
|
|
||||||
inline ~CreateVector() {
|
inline ~FastVector() {
|
||||||
std::free(data_);
|
std::destroy(data_, data_ + size_);
|
||||||
|
if (heapAllocated_) std::free(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline CreateVector(const CreateVector&) = delete;
|
// Copy constructor
|
||||||
inline CreateVector& operator=(const CreateVector&) = delete;
|
FastVector(const FastVector& other) {
|
||||||
|
reserve(other.size_);
|
||||||
inline CreateVector(CreateVector&& other) noexcept
|
if constexpr (std::is_trivially_copyable_v<T>) {
|
||||||
: data_(other.data_), size_(other.size_), capacity_(other.capacity_) {
|
std::memcpy(data_, other.data_, other.size_ * sizeof(T));
|
||||||
other.data_ = nullptr;
|
} else {
|
||||||
other.size_ = 0;
|
std::uninitialized_copy(other.data_, other.data_ + other.size_, data_);
|
||||||
other.capacity_ = 0;
|
}
|
||||||
|
size_ = other.size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline CreateVector& operator=(CreateVector&& other) noexcept {
|
// Move constructor
|
||||||
if (this != &other) {
|
FastVector(FastVector&& other) noexcept {
|
||||||
std::free(data_);
|
if (other.heapAllocated_) {
|
||||||
data_ = other.data_;
|
data_ = other.data_;
|
||||||
size_ = other.size_;
|
size_ = other.size_;
|
||||||
capacity_ = other.capacity_;
|
capacity_ = other.capacity_;
|
||||||
other.data_ = nullptr;
|
heapAllocated_ = true;
|
||||||
other.size_ = 0;
|
} else {
|
||||||
other.capacity_ = 0;
|
std::uninitialized_move(other.data_, other.data_ + other.size_, data_);
|
||||||
|
}
|
||||||
|
other.data_ = reinterpret_cast<T*>(other.sbo_);
|
||||||
|
other.size_ = 0;
|
||||||
|
other.capacity_ = SBO_CAP;
|
||||||
|
other.heapAllocated_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy assignment
|
||||||
|
FastVector& operator=(const FastVector& other) {
|
||||||
|
if (this != &other) {
|
||||||
|
clear();
|
||||||
|
reserve(other.size_);
|
||||||
|
if constexpr (std::is_trivially_copyable_v<T>) {
|
||||||
|
std::memcpy(data_, other.data_, other.size_ * sizeof(T));
|
||||||
|
} else {
|
||||||
|
std::uninitialized_copy(other.data_, other.data_ + other.size_, data_);
|
||||||
|
}
|
||||||
|
size_ = other.size_;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void push_back(const T& value) {
|
// Move assignment
|
||||||
if (size_ == capacity_) grow(size_ + 1);
|
FastVector& operator=(FastVector&& other) noexcept {
|
||||||
data_[size_++] = value;
|
if (this != &other) {
|
||||||
|
clear();
|
||||||
|
if (heapAllocated_) std::free(data_);
|
||||||
|
|
||||||
|
if (other.heapAllocated_) {
|
||||||
|
data_ = other.data_;
|
||||||
|
size_ = other.size_;
|
||||||
|
capacity_ = other.capacity_;
|
||||||
|
heapAllocated_ = true;
|
||||||
|
} else {
|
||||||
|
std::uninitialized_move(other.data_, other.data_ + other.size_, data_);
|
||||||
|
}
|
||||||
|
|
||||||
|
other.data_ = reinterpret_cast<T*>(other.sbo_);
|
||||||
|
other.size_ = 0;
|
||||||
|
other.capacity_ = SBO_CAP;
|
||||||
|
other.heapAllocated_ = false;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void push_back(T&& value) {
|
inline void push_back(const T& val) {
|
||||||
if (size_ == capacity_) grow(size_ + 1);
|
if (size_ == capacity_) reallocate(capacity_ * 2);
|
||||||
data_[size_++] = std::move(value);
|
new (data_ + size_) T(val);
|
||||||
|
++size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void push_back(T&& val) {
|
||||||
|
if (size_ == capacity_) reallocate(capacity_ * 2);
|
||||||
|
new (data_ + size_) T(std::move(val));
|
||||||
|
++size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void pop_back() {
|
inline void pop_back() {
|
||||||
assert(size_ > 0);
|
FV_ASSERT(size_ > 0);
|
||||||
--size_;
|
--size_;
|
||||||
|
std::destroy_at(data_ + size_);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void clear() {
|
inline void clear() {
|
||||||
|
std::destroy(data_, data_ + size_);
|
||||||
size_ = 0;
|
size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void reserve(size_t newCap) {
|
||||||
|
if (newCap > capacity_) reallocate(newCap);
|
||||||
|
}
|
||||||
|
|
||||||
inline void resize(size_t newSize) {
|
inline void resize(size_t newSize) {
|
||||||
if (newSize > capacity_) grow(newSize);
|
if (newSize > capacity_) reallocate(newSize);
|
||||||
|
if (newSize > size_) {
|
||||||
|
std::uninitialized_value_construct(data_ + size_, data_ + newSize);
|
||||||
|
} else {
|
||||||
|
std::destroy(data_ + newSize, data_ + size_);
|
||||||
|
}
|
||||||
size_ = newSize;
|
size_ = newSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reserve(size_t newCap) {
|
inline T& operator[](size_t i) {
|
||||||
if (newCap > capacity_) grow(newCap);
|
FV_ASSERT(i < size_);
|
||||||
|
return data_[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline T& operator[](size_t index) {
|
inline const T& operator[](size_t i) const {
|
||||||
assert(index < size_);
|
FV_ASSERT(i < size_);
|
||||||
return data_[index];
|
return data_[i];
|
||||||
}
|
|
||||||
|
|
||||||
inline const T& operator[](size_t index) const {
|
|
||||||
assert(index < size_);
|
|
||||||
return data_[index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline T* data() { return data_; }
|
inline T* data() { return data_; }
|
||||||
|
Loading…
Reference in New Issue
Block a user