Revert "BLI: refactor how buffers for small object optimization are stored"
This reverts commit 5d79f9f276b4b3e6289308c534c58e7ee3bb5e2d. This was introducing build errors in windows. Need a bit more time to check it.
This commit is contained in:
parent
5d79f9f276
commit
247a28f242
@ -74,7 +74,7 @@ class Array {
|
||||
Allocator allocator_;
|
||||
|
||||
/** A placeholder buffer that will remain uninitialized until it is used. */
|
||||
TypedBuffer<T, InlineBufferCapacity> inline_buffer_;
|
||||
AlignedBuffer<sizeof(T) * InlineBufferCapacity, alignof(T)> inline_buffer_;
|
||||
|
||||
public:
|
||||
/**
|
||||
@ -82,7 +82,7 @@ class Array {
|
||||
*/
|
||||
Array()
|
||||
{
|
||||
data_ = inline_buffer_;
|
||||
data_ = this->inline_buffer();
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ class Array {
|
||||
uninitialized_relocate_n(other.data_, size_, data_);
|
||||
}
|
||||
|
||||
other.data_ = other.inline_buffer_;
|
||||
other.data_ = other.inline_buffer();
|
||||
other.size_ = 0;
|
||||
}
|
||||
|
||||
@ -335,13 +335,18 @@ class Array {
|
||||
T *get_buffer_for_size(uint size)
|
||||
{
|
||||
if (size <= InlineBufferCapacity) {
|
||||
return inline_buffer_;
|
||||
return this->inline_buffer();
|
||||
}
|
||||
else {
|
||||
return this->allocate(size);
|
||||
}
|
||||
}
|
||||
|
||||
T *inline_buffer() const
|
||||
{
|
||||
return (T *)inline_buffer_.ptr();
|
||||
}
|
||||
|
||||
T *allocate(uint size)
|
||||
{
|
||||
return (T *)allocator_.allocate(size * sizeof(T), alignof(T), AT);
|
||||
@ -349,7 +354,7 @@ class Array {
|
||||
|
||||
bool uses_inline_buffer() const
|
||||
{
|
||||
return data_ == inline_buffer_;
|
||||
return data_ == this->inline_buffer();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -53,8 +53,8 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
};
|
||||
|
||||
State state_;
|
||||
TypedBuffer<Key> key_buffer_;
|
||||
TypedBuffer<Value> value_buffer_;
|
||||
AlignedBuffer<sizeof(Key), alignof(Key)> key_buffer_;
|
||||
AlignedBuffer<sizeof(Value), alignof(Value)> value_buffer_;
|
||||
|
||||
public:
|
||||
/**
|
||||
@ -71,8 +71,8 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
~SimpleMapSlot()
|
||||
{
|
||||
if (state_ == Occupied) {
|
||||
key_buffer_->~Key();
|
||||
value_buffer_->~Value();
|
||||
this->key()->~Key();
|
||||
this->value()->~Value();
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,8 +84,8 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
{
|
||||
state_ = other.state_;
|
||||
if (other.state_ == Occupied) {
|
||||
new (&key_buffer_) Key(*other.key_buffer_);
|
||||
new (&value_buffer_) Value(*other.value_buffer_);
|
||||
new ((void *)this->key()) Key(*other.key());
|
||||
new ((void *)this->value()) Value(*other.value());
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,8 +98,8 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
{
|
||||
state_ = other.state_;
|
||||
if (other.state_ == Occupied) {
|
||||
new (&key_buffer_) Key(std::move(*other.key_buffer_));
|
||||
new (&value_buffer_) Value(std::move(*other.value_buffer_));
|
||||
new ((void *)this->key()) Key(std::move(*other.key()));
|
||||
new ((void *)this->value()) Value(std::move(*other.value()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
*/
|
||||
Key *key()
|
||||
{
|
||||
return key_buffer_;
|
||||
return (Key *)key_buffer_.ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,7 +116,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
*/
|
||||
const Key *key() const
|
||||
{
|
||||
return key_buffer_;
|
||||
return (const Key *)key_buffer_.ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,7 +124,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
*/
|
||||
Value *value()
|
||||
{
|
||||
return value_buffer_;
|
||||
return (Value *)value_buffer_.ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,7 +132,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
*/
|
||||
const Value *value() const
|
||||
{
|
||||
return value_buffer_;
|
||||
return (const Value *)value_buffer_.ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -158,7 +158,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
template<typename Hash> uint32_t get_hash(const Hash &hash)
|
||||
{
|
||||
BLI_assert(this->is_occupied());
|
||||
return hash(*key_buffer_);
|
||||
return hash(*this->key());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,10 +170,10 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
BLI_assert(!this->is_occupied());
|
||||
BLI_assert(other.is_occupied());
|
||||
state_ = Occupied;
|
||||
new (&key_buffer_) Key(std::move(*other.key_buffer_));
|
||||
new (&value_buffer_) Value(std::move(*other.value_buffer_));
|
||||
other.key_buffer_->~Key();
|
||||
other.value_buffer_->~Value();
|
||||
new ((void *)this->key()) Key(std::move(*other.key()));
|
||||
new ((void *)this->value()) Value(std::move(*other.value()));
|
||||
other.key()->~Key();
|
||||
other.value()->~Value();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,7 +184,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
bool contains(const ForwardKey &key, const IsEqual &is_equal, uint32_t UNUSED(hash)) const
|
||||
{
|
||||
if (state_ == Occupied) {
|
||||
return is_equal(key, *key_buffer_);
|
||||
return is_equal(key, *this->key());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -198,7 +198,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
{
|
||||
BLI_assert(!this->is_occupied());
|
||||
this->occupy_without_value(std::forward<ForwardKey>(key), hash);
|
||||
new (&value_buffer_) Value(std::forward<ForwardValue>(value));
|
||||
new ((void *)this->value()) Value(std::forward<ForwardValue>(value));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -209,7 +209,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
{
|
||||
BLI_assert(!this->is_occupied());
|
||||
state_ = Occupied;
|
||||
new (&key_buffer_) Key(std::forward<ForwardKey>(key));
|
||||
new ((void *)this->key()) Key(std::forward<ForwardKey>(key));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -220,8 +220,8 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
{
|
||||
BLI_assert(this->is_occupied());
|
||||
state_ = Removed;
|
||||
key_buffer_->~Key();
|
||||
value_buffer_->~Value();
|
||||
this->key()->~Key();
|
||||
this->value()->~Value();
|
||||
}
|
||||
};
|
||||
|
||||
@ -236,7 +236,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
||||
template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot {
|
||||
private:
|
||||
Key key_ = KeyInfo::get_empty();
|
||||
TypedBuffer<Value> value_buffer_;
|
||||
AlignedBuffer<sizeof(Value), alignof(Value)> value_buffer_;
|
||||
|
||||
public:
|
||||
IntrusiveMapSlot() = default;
|
||||
@ -244,21 +244,21 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot
|
||||
~IntrusiveMapSlot()
|
||||
{
|
||||
if (KeyInfo::is_not_empty_or_removed(key_)) {
|
||||
value_buffer_->~Value();
|
||||
this->value()->~Value();
|
||||
}
|
||||
}
|
||||
|
||||
IntrusiveMapSlot(const IntrusiveMapSlot &other) : key_(other.key_)
|
||||
{
|
||||
if (KeyInfo::is_not_empty_or_removed(key_)) {
|
||||
new (&value_buffer_) Value(*other.value_buffer_);
|
||||
new ((void *)this->value()) Value(*other.value());
|
||||
}
|
||||
}
|
||||
|
||||
IntrusiveMapSlot(IntrusiveMapSlot &&other) noexcept : key_(other.key_)
|
||||
{
|
||||
if (KeyInfo::is_not_empty_or_removed(key_)) {
|
||||
new (&value_buffer_) Value(std::move(*other.value_buffer_));
|
||||
new ((void *)this->value()) Value(std::move(*other.value()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,12 +274,12 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot
|
||||
|
||||
Value *value()
|
||||
{
|
||||
return value_buffer_;
|
||||
return (Value *)value_buffer_.ptr();
|
||||
}
|
||||
|
||||
const Value *value() const
|
||||
{
|
||||
return value_buffer_;
|
||||
return (const Value *)value_buffer_.ptr();
|
||||
}
|
||||
|
||||
bool is_occupied() const
|
||||
@ -295,7 +295,7 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot
|
||||
template<typename Hash> uint32_t get_hash(const Hash &hash)
|
||||
{
|
||||
BLI_assert(this->is_occupied());
|
||||
return hash(key_);
|
||||
return hash(*this->key());
|
||||
}
|
||||
|
||||
void relocate_occupied_here(IntrusiveMapSlot &other, uint32_t UNUSED(hash))
|
||||
@ -303,9 +303,9 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot
|
||||
BLI_assert(!this->is_occupied());
|
||||
BLI_assert(other.is_occupied());
|
||||
key_ = std::move(other.key_);
|
||||
new (&value_buffer_) Value(std::move(*other.value_buffer_));
|
||||
new ((void *)this->value()) Value(std::move(*other.value()));
|
||||
other.key_.~Key();
|
||||
other.value_buffer_->~Value();
|
||||
other.value()->~Value();
|
||||
}
|
||||
|
||||
template<typename ForwardKey, typename IsEqual>
|
||||
@ -321,7 +321,7 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot
|
||||
BLI_assert(!this->is_occupied());
|
||||
BLI_assert(KeyInfo::is_not_empty_or_removed(key));
|
||||
this->occupy_without_value(std::forward<ForwardKey>(key), hash);
|
||||
new (&value_buffer_) Value(std::forward<ForwardValue>(value));
|
||||
new ((void *)this->value()) Value(std::forward<ForwardValue>(value));
|
||||
}
|
||||
|
||||
template<typename ForwardKey> void occupy_without_value(ForwardKey &&key, uint32_t UNUSED(hash))
|
||||
@ -335,7 +335,7 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot
|
||||
{
|
||||
BLI_assert(this->is_occupied());
|
||||
KeyInfo::remove(key_);
|
||||
value_buffer_->~Value();
|
||||
this->value()->~Value();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -218,8 +218,12 @@ template<typename T> struct DestructValueAtAddress {
|
||||
template<typename T> using destruct_ptr = std::unique_ptr<T, DestructValueAtAddress<T>>;
|
||||
|
||||
/**
|
||||
* An `AlignedBuffer` is a byte array with at least the given size and alignment. The buffer will
|
||||
* An `AlignedBuffer` is simply a byte array with the given size and alignment. The buffer will
|
||||
* not be initialized by the default constructor.
|
||||
*
|
||||
* This can be used to reserve memory for C++ objects whose lifetime is different from the
|
||||
* lifetime of the object they are embedded in. It's used by containers with small buffer
|
||||
* optimization and hash table implementations.
|
||||
*/
|
||||
template<size_t Size, size_t Alignment> class alignas(Alignment) AlignedBuffer {
|
||||
private:
|
||||
@ -227,16 +231,6 @@ template<size_t Size, size_t Alignment> class alignas(Alignment) AlignedBuffer {
|
||||
char buffer_[(Size > 0) ? Size : 1];
|
||||
|
||||
public:
|
||||
operator void *()
|
||||
{
|
||||
return (void *)buffer_;
|
||||
}
|
||||
|
||||
operator const void *() const
|
||||
{
|
||||
return (void *)buffer_;
|
||||
}
|
||||
|
||||
void *ptr()
|
||||
{
|
||||
return (void *)buffer_;
|
||||
@ -248,57 +242,6 @@ template<size_t Size, size_t Alignment> class alignas(Alignment) AlignedBuffer {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This can be used to reserve memory for C++ objects whose lifetime is different from the
|
||||
* lifetime of the object they are embedded in. It's used by containers with small buffer
|
||||
* optimization and hash table implementations.
|
||||
*/
|
||||
template<typename T, size_t Size = 1> class TypedBuffer {
|
||||
private:
|
||||
AlignedBuffer<sizeof(T) * Size, alignof(T)> buffer_;
|
||||
|
||||
public:
|
||||
operator T *()
|
||||
{
|
||||
return (T *)&buffer_;
|
||||
}
|
||||
|
||||
operator const T *() const
|
||||
{
|
||||
return (const T *)&buffer_;
|
||||
}
|
||||
|
||||
T *operator->()
|
||||
{
|
||||
return (T *)&buffer_;
|
||||
}
|
||||
|
||||
const T *operator->() const
|
||||
{
|
||||
return (const T *)&buffer_;
|
||||
}
|
||||
|
||||
T &operator*()
|
||||
{
|
||||
return *(T *)&buffer_;
|
||||
}
|
||||
|
||||
const T &operator*() const
|
||||
{
|
||||
return *(const T *)&buffer_;
|
||||
}
|
||||
|
||||
T *ptr()
|
||||
{
|
||||
return (T *)&buffer_;
|
||||
}
|
||||
|
||||
const T *ptr() const
|
||||
{
|
||||
return (const T *)&buffer_;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This can be used by container constructors. A parameter of this type should be used to indicate
|
||||
* that the constructor does not construct the elements.
|
||||
|
@ -51,7 +51,7 @@ template<typename Key> class SimpleSetSlot {
|
||||
};
|
||||
|
||||
State state_;
|
||||
TypedBuffer<Key> key_buffer_;
|
||||
AlignedBuffer<sizeof(Key), alignof(Key)> buffer_;
|
||||
|
||||
public:
|
||||
/**
|
||||
@ -68,7 +68,7 @@ template<typename Key> class SimpleSetSlot {
|
||||
~SimpleSetSlot()
|
||||
{
|
||||
if (state_ == Occupied) {
|
||||
key_buffer_->~Key();
|
||||
this->key()->~Key();
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ template<typename Key> class SimpleSetSlot {
|
||||
{
|
||||
state_ = other.state_;
|
||||
if (other.state_ == Occupied) {
|
||||
new (&key_buffer_) Key(*other.key_buffer_);
|
||||
new ((void *)this->key()) Key(*other.key());
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ template<typename Key> class SimpleSetSlot {
|
||||
{
|
||||
state_ = other.state_;
|
||||
if (other.state_ == Occupied) {
|
||||
new (&key_buffer_) Key(std::move(*other.key_buffer_));
|
||||
new ((void *)this->key()) Key(std::move(*other.key()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ template<typename Key> class SimpleSetSlot {
|
||||
*/
|
||||
Key *key()
|
||||
{
|
||||
return key_buffer_;
|
||||
return (Key *)buffer_.ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,7 +110,7 @@ template<typename Key> class SimpleSetSlot {
|
||||
*/
|
||||
const Key *key() const
|
||||
{
|
||||
return key_buffer_;
|
||||
return (const Key *)buffer_.ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,7 +136,7 @@ template<typename Key> class SimpleSetSlot {
|
||||
template<typename Hash> uint32_t get_hash(const Hash &hash) const
|
||||
{
|
||||
BLI_assert(this->is_occupied());
|
||||
return hash(*key_buffer_);
|
||||
return hash(*this->key());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,8 +148,8 @@ template<typename Key> class SimpleSetSlot {
|
||||
BLI_assert(!this->is_occupied());
|
||||
BLI_assert(other.is_occupied());
|
||||
state_ = Occupied;
|
||||
new (&key_buffer_) Key(std::move(*other.key_buffer_));
|
||||
other.key_buffer_->~Key();
|
||||
new ((void *)this->key()) Key(std::move(*other.key()));
|
||||
other.key()->~Key();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -160,7 +160,7 @@ template<typename Key> class SimpleSetSlot {
|
||||
bool contains(const ForwardKey &key, const IsEqual &is_equal, uint32_t UNUSED(hash)) const
|
||||
{
|
||||
if (state_ == Occupied) {
|
||||
return is_equal(key, *key_buffer_);
|
||||
return is_equal(key, *this->key());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -173,7 +173,7 @@ template<typename Key> class SimpleSetSlot {
|
||||
{
|
||||
BLI_assert(!this->is_occupied());
|
||||
state_ = Occupied;
|
||||
new (&key_buffer_) Key(std::forward<ForwardKey>(key));
|
||||
new ((void *)this->key()) Key(std::forward<ForwardKey>(key));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -183,7 +183,7 @@ template<typename Key> class SimpleSetSlot {
|
||||
{
|
||||
BLI_assert(this->is_occupied());
|
||||
state_ = Removed;
|
||||
key_buffer_->~Key();
|
||||
this->key()->~Key();
|
||||
}
|
||||
};
|
||||
|
||||
@ -201,7 +201,7 @@ template<typename Key> class HashedSetSlot {
|
||||
|
||||
uint32_t hash_;
|
||||
State state_;
|
||||
TypedBuffer<Key> key_buffer_;
|
||||
AlignedBuffer<sizeof(Key), alignof(Key)> buffer_;
|
||||
|
||||
public:
|
||||
HashedSetSlot()
|
||||
@ -212,7 +212,7 @@ template<typename Key> class HashedSetSlot {
|
||||
~HashedSetSlot()
|
||||
{
|
||||
if (state_ == Occupied) {
|
||||
key_buffer_->~Key();
|
||||
this->key()->~Key();
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +221,7 @@ template<typename Key> class HashedSetSlot {
|
||||
state_ = other.state_;
|
||||
if (other.state_ == Occupied) {
|
||||
hash_ = other.hash_;
|
||||
new (&key_buffer_) Key(*other.key_buffer_);
|
||||
new ((void *)this->key()) Key(*other.key());
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,18 +230,18 @@ template<typename Key> class HashedSetSlot {
|
||||
state_ = other.state_;
|
||||
if (other.state_ == Occupied) {
|
||||
hash_ = other.hash_;
|
||||
new (&key_buffer_) Key(std::move(*other.key_buffer_));
|
||||
new ((void *)this->key()) Key(std::move(*other.key()));
|
||||
}
|
||||
}
|
||||
|
||||
Key *key()
|
||||
{
|
||||
return key_buffer_;
|
||||
return (Key *)buffer_.ptr();
|
||||
}
|
||||
|
||||
const Key *key() const
|
||||
{
|
||||
return key_buffer_;
|
||||
return (const Key *)buffer_.ptr();
|
||||
}
|
||||
|
||||
bool is_occupied() const
|
||||
@ -266,8 +266,8 @@ template<typename Key> class HashedSetSlot {
|
||||
BLI_assert(other.is_occupied());
|
||||
state_ = Occupied;
|
||||
hash_ = hash;
|
||||
new (&key_buffer_) Key(std::move(*other.key_buffer_));
|
||||
key_buffer_->~Key();
|
||||
new ((void *)this->key()) Key(std::move(*other.key()));
|
||||
other.key()->~Key();
|
||||
}
|
||||
|
||||
template<typename ForwardKey, typename IsEqual>
|
||||
@ -276,7 +276,7 @@ template<typename Key> class HashedSetSlot {
|
||||
/* hash_ might be uninitialized here, but that is ok. */
|
||||
if (hash_ == hash) {
|
||||
if (state_ == Occupied) {
|
||||
return is_equal(key, *key_buffer_);
|
||||
return is_equal(key, *this->key());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -287,14 +287,14 @@ template<typename Key> class HashedSetSlot {
|
||||
BLI_assert(!this->is_occupied());
|
||||
state_ = Occupied;
|
||||
hash_ = hash;
|
||||
new (&key_buffer_) Key(std::forward<ForwardKey>(key));
|
||||
new ((void *)this->key()) Key(std::forward<ForwardKey>(key));
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
BLI_assert(this->is_occupied());
|
||||
state_ = Removed;
|
||||
key_buffer_->~Key();
|
||||
this->key()->~Key();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -106,7 +106,7 @@ class Stack {
|
||||
uint size_;
|
||||
|
||||
/** The buffer used to implement small object optimization. */
|
||||
TypedBuffer<T, InlineBufferCapacity> inline_buffer_;
|
||||
AlignedBuffer<sizeof(T) * InlineBufferCapacity, alignof(T)> inline_buffer_;
|
||||
|
||||
/**
|
||||
* A chunk referencing the inline buffer. This is always the bottom-most chunk.
|
||||
@ -123,12 +123,14 @@ class Stack {
|
||||
*/
|
||||
Stack(Allocator allocator = {}) : allocator_(allocator)
|
||||
{
|
||||
T *inline_buffer = this->inline_buffer();
|
||||
|
||||
inline_chunk_.below = nullptr;
|
||||
inline_chunk_.above = nullptr;
|
||||
inline_chunk_.begin = inline_buffer_;
|
||||
inline_chunk_.capacity_end = inline_buffer_ + InlineBufferCapacity;
|
||||
inline_chunk_.begin = inline_buffer;
|
||||
inline_chunk_.capacity_end = inline_buffer + InlineBufferCapacity;
|
||||
|
||||
top_ = inline_buffer_;
|
||||
top_ = inline_buffer;
|
||||
top_chunk_ = &inline_chunk_;
|
||||
size_ = 0;
|
||||
}
|
||||
@ -166,8 +168,8 @@ class Stack {
|
||||
|
||||
Stack(Stack &&other) noexcept : Stack(other.allocator_)
|
||||
{
|
||||
uninitialized_relocate_n<T>(
|
||||
other.inline_buffer_, std::min(other.size_, InlineBufferCapacity), inline_buffer_);
|
||||
uninitialized_relocate_n(
|
||||
other.inline_buffer(), std::min(other.size_, InlineBufferCapacity), this->inline_buffer());
|
||||
|
||||
inline_chunk_.above = other.inline_chunk_.above;
|
||||
size_ = other.size_;
|
||||
@ -178,7 +180,7 @@ class Stack {
|
||||
|
||||
if (size_ <= InlineBufferCapacity) {
|
||||
top_chunk_ = &inline_chunk_;
|
||||
top_ = inline_buffer_ + size_;
|
||||
top_ = this->inline_buffer() + size_;
|
||||
}
|
||||
else {
|
||||
top_chunk_ = other.top_chunk_;
|
||||
@ -337,6 +339,11 @@ class Stack {
|
||||
}
|
||||
|
||||
private:
|
||||
T *inline_buffer() const
|
||||
{
|
||||
return (T *)inline_buffer_.ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes top_chunk_ to point to a new chunk that is above the current one. The new chunk might
|
||||
* be smaller than the given size_hint. This happens when a chunk that has been allocated before
|
||||
|
@ -92,7 +92,7 @@ class Vector {
|
||||
Allocator allocator_;
|
||||
|
||||
/** A placeholder buffer that will remain uninitialized until it is used. */
|
||||
TypedBuffer<T, InlineBufferCapacity> inline_buffer_;
|
||||
AlignedBuffer<(uint)sizeof(T) * InlineBufferCapacity, (uint)alignof(T)> inline_buffer_;
|
||||
|
||||
/**
|
||||
* Store the size of the vector explicitly in debug builds. Otherwise you'd always have to call
|
||||
@ -120,7 +120,7 @@ class Vector {
|
||||
*/
|
||||
Vector()
|
||||
{
|
||||
begin_ = inline_buffer_;
|
||||
begin_ = this->inline_buffer();
|
||||
end_ = begin_;
|
||||
capacity_end_ = begin_ + InlineBufferCapacity;
|
||||
UPDATE_VECTOR_SIZE(this);
|
||||
@ -227,7 +227,7 @@ class Vector {
|
||||
if (other.is_inline()) {
|
||||
if (size <= InlineBufferCapacity) {
|
||||
/* Copy between inline buffers. */
|
||||
begin_ = inline_buffer_;
|
||||
begin_ = this->inline_buffer();
|
||||
end_ = begin_ + size;
|
||||
capacity_end_ = begin_ + InlineBufferCapacity;
|
||||
uninitialized_relocate_n(other.begin_, size, begin_);
|
||||
@ -248,7 +248,7 @@ class Vector {
|
||||
capacity_end_ = other.capacity_end_;
|
||||
}
|
||||
|
||||
other.begin_ = other.inline_buffer_;
|
||||
other.begin_ = other.inline_buffer();
|
||||
other.end_ = other.begin_;
|
||||
other.capacity_end_ = other.begin_ + OtherInlineBufferCapacity;
|
||||
UPDATE_VECTOR_SIZE(this);
|
||||
@ -399,7 +399,7 @@ class Vector {
|
||||
allocator_.deallocate(begin_);
|
||||
}
|
||||
|
||||
begin_ = inline_buffer_;
|
||||
begin_ = this->inline_buffer();
|
||||
end_ = begin_;
|
||||
capacity_end_ = begin_ + InlineBufferCapacity;
|
||||
UPDATE_VECTOR_SIZE(this);
|
||||
@ -763,9 +763,14 @@ class Vector {
|
||||
}
|
||||
|
||||
private:
|
||||
T *inline_buffer() const
|
||||
{
|
||||
return (T *)inline_buffer_.ptr();
|
||||
}
|
||||
|
||||
bool is_inline() const
|
||||
{
|
||||
return begin_ == inline_buffer_;
|
||||
return begin_ == this->inline_buffer();
|
||||
}
|
||||
|
||||
void ensure_space_for_one()
|
||||
@ -812,7 +817,7 @@ class Vector {
|
||||
uint capacity;
|
||||
|
||||
if (size <= InlineBufferCapacity) {
|
||||
begin_ = inline_buffer_;
|
||||
begin_ = this->inline_buffer();
|
||||
capacity = InlineBufferCapacity;
|
||||
}
|
||||
else {
|
||||
|
@ -138,22 +138,23 @@ TEST(array, NoInitializationSizeConstructor)
|
||||
{
|
||||
using MyArray = Array<ConstructibleType>;
|
||||
|
||||
TypedBuffer<MyArray> buffer;
|
||||
memset(buffer, 100, sizeof(MyArray));
|
||||
AlignedBuffer<sizeof(MyArray), alignof(MyArray)> buffer;
|
||||
char *buffer_ptr = (char *)buffer.ptr();
|
||||
memset(buffer_ptr, 100, sizeof(MyArray));
|
||||
|
||||
/* Doing this to avoid some compiler optimization. */
|
||||
for (uint i : IndexRange(sizeof(MyArray))) {
|
||||
EXPECT_EQ(((char *)buffer.ptr())[i], 100);
|
||||
EXPECT_EQ(buffer_ptr[i], 100);
|
||||
}
|
||||
|
||||
{
|
||||
MyArray &array = *new (buffer) MyArray(1, NoInitialization());
|
||||
MyArray &array = *new (buffer.ptr()) MyArray(1, NoInitialization());
|
||||
EXPECT_EQ(array[0].value, 100);
|
||||
array.clear_without_destruct();
|
||||
array.~Array();
|
||||
}
|
||||
{
|
||||
MyArray &array = *new (buffer) MyArray(1);
|
||||
MyArray &array = *new (buffer.ptr()) MyArray(1);
|
||||
EXPECT_EQ(array[0].value, 42);
|
||||
array.~Array();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user