Export of internal Abseil changes.
-- 4a7dc9bd72a50f493671ea3ae2a571462cb70fc4 by Jon Cohen <cohenjon@google.com>: Use -ignore instead of /ignore. CMake was interpreting /ignore as a path and changing it it \ignore in windows builds, expecting it to be some sort of file. Close #293 PiperOrigin-RevId: 242134552 -- 8de3e403667f677859584bb321ef8fce3253af18 by CJ Johnson <johnsoncj@google.com>: In InlinedVector: Migrates `Rep` to `Data` getting rid of the `Allocation` class. PiperOrigin-RevId: 242130255 GitOrigin-RevId: 4a7dc9bd72a50f493671ea3ae2a571462cb70fc4 Change-Id: Ic7ff4c572bba7a411155bf304b9cae10d68599db
This commit is contained in:
parent
666fc1266b
commit
6cc6ac44e0
5 changed files with 95 additions and 101 deletions
|
@ -70,7 +70,7 @@ class InlinedVector {
|
||||||
N > 0, "InlinedVector cannot be instantiated with `0` inlined elements.");
|
N > 0, "InlinedVector cannot be instantiated with `0` inlined elements.");
|
||||||
|
|
||||||
using Storage = inlined_vector_internal::Storage<InlinedVector>;
|
using Storage = inlined_vector_internal::Storage<InlinedVector>;
|
||||||
using Allocation = typename Storage::Allocation;
|
using AllocatorTraits = typename Storage::AllocatorTraits;
|
||||||
|
|
||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
using IsAtLeastForwardIterator = std::is_convertible<
|
using IsAtLeastForwardIterator = std::is_convertible<
|
||||||
|
@ -198,7 +198,8 @@ class InlinedVector {
|
||||||
if (other.storage_.GetIsAllocated()) {
|
if (other.storage_.GetIsAllocated()) {
|
||||||
// We can just steal the underlying buffer from the source.
|
// We can just steal the underlying buffer from the source.
|
||||||
// That leaves the source empty, so we clear its size.
|
// That leaves the source empty, so we clear its size.
|
||||||
storage_.InitAllocation(other.storage_.GetAllocation());
|
storage_.SetAllocatedData(other.storage_.GetAllocatedData());
|
||||||
|
storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity());
|
||||||
storage_.SetAllocatedSize(other.size());
|
storage_.SetAllocatedSize(other.size());
|
||||||
other.storage_.SetInlinedSize(0);
|
other.storage_.SetInlinedSize(0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -231,7 +232,8 @@ class InlinedVector {
|
||||||
if (alloc == other.storage_.GetAllocator()) {
|
if (alloc == other.storage_.GetAllocator()) {
|
||||||
// We can just steal the allocation from the source.
|
// We can just steal the allocation from the source.
|
||||||
storage_.SetAllocatedSize(other.size());
|
storage_.SetAllocatedSize(other.size());
|
||||||
storage_.InitAllocation(other.storage_.GetAllocation());
|
storage_.SetAllocatedData(other.storage_.GetAllocatedData());
|
||||||
|
storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity());
|
||||||
other.storage_.SetInlinedSize(0);
|
other.storage_.SetInlinedSize(0);
|
||||||
} else {
|
} else {
|
||||||
// We need to use our own allocator
|
// We need to use our own allocator
|
||||||
|
@ -484,7 +486,8 @@ class InlinedVector {
|
||||||
if (other.storage_.GetIsAllocated()) {
|
if (other.storage_.GetIsAllocated()) {
|
||||||
clear();
|
clear();
|
||||||
storage_.SetAllocatedSize(other.size());
|
storage_.SetAllocatedSize(other.size());
|
||||||
storage_.InitAllocation(other.storage_.GetAllocation());
|
storage_.SetAllocatedData(other.storage_.GetAllocatedData());
|
||||||
|
storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity());
|
||||||
other.storage_.SetInlinedSize(0);
|
other.storage_.SetInlinedSize(0);
|
||||||
} else {
|
} else {
|
||||||
if (storage_.GetIsAllocated()) clear();
|
if (storage_.GetIsAllocated()) clear();
|
||||||
|
@ -789,7 +792,9 @@ class InlinedVector {
|
||||||
size_type s = size();
|
size_type s = size();
|
||||||
if (storage_.GetIsAllocated()) {
|
if (storage_.GetIsAllocated()) {
|
||||||
Destroy(storage_.GetAllocatedData(), storage_.GetAllocatedData() + s);
|
Destroy(storage_.GetAllocatedData(), storage_.GetAllocatedData() + s);
|
||||||
storage_.GetAllocation().Dealloc(storage_.GetAllocator());
|
AllocatorTraits::deallocate(storage_.GetAllocator(),
|
||||||
|
storage_.GetAllocatedData(),
|
||||||
|
storage_.GetAllocatedCapacity());
|
||||||
} else if (s != 0) { // do nothing for empty vectors
|
} else if (s != 0) { // do nothing for empty vectors
|
||||||
Destroy(storage_.GetInlinedData(), storage_.GetInlinedData() + s);
|
Destroy(storage_.GetInlinedData(), storage_.GetInlinedData() + s);
|
||||||
}
|
}
|
||||||
|
@ -841,11 +846,11 @@ class InlinedVector {
|
||||||
// Reallocate storage and move elements.
|
// Reallocate storage and move elements.
|
||||||
// We can't simply use the same approach as above, because `assign()` would
|
// We can't simply use the same approach as above, because `assign()` would
|
||||||
// call into `reserve()` internally and reserve larger capacity than we need
|
// call into `reserve()` internally and reserve larger capacity than we need
|
||||||
Allocation new_allocation(storage_.GetAllocator(), s);
|
pointer new_data = AllocatorTraits::allocate(storage_.GetAllocator(), s);
|
||||||
UninitializedCopy(std::make_move_iterator(storage_.GetAllocatedData()),
|
UninitializedCopy(std::make_move_iterator(storage_.GetAllocatedData()),
|
||||||
std::make_move_iterator(storage_.GetAllocatedData() + s),
|
std::make_move_iterator(storage_.GetAllocatedData() + s),
|
||||||
new_allocation.buffer());
|
new_data);
|
||||||
ResetAllocation(new_allocation, s);
|
ResetAllocation(new_data, s, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// `InlinedVector::swap()`
|
// `InlinedVector::swap()`
|
||||||
|
@ -861,17 +866,21 @@ class InlinedVector {
|
||||||
template <typename H, typename TheT, size_t TheN, typename TheA>
|
template <typename H, typename TheT, size_t TheN, typename TheA>
|
||||||
friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a);
|
friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a);
|
||||||
|
|
||||||
void ResetAllocation(Allocation new_allocation, size_type new_size) {
|
void ResetAllocation(pointer new_data, size_type new_capacity,
|
||||||
|
size_type new_size) {
|
||||||
if (storage_.GetIsAllocated()) {
|
if (storage_.GetIsAllocated()) {
|
||||||
Destroy(storage_.GetAllocatedData(),
|
Destroy(storage_.GetAllocatedData(),
|
||||||
storage_.GetAllocatedData() + size());
|
storage_.GetAllocatedData() + size());
|
||||||
assert(begin() == storage_.GetAllocatedData());
|
assert(begin() == storage_.GetAllocatedData());
|
||||||
storage_.GetAllocation().Dealloc(storage_.GetAllocator());
|
AllocatorTraits::deallocate(storage_.GetAllocator(),
|
||||||
storage_.GetAllocation() = new_allocation;
|
storage_.GetAllocatedData(),
|
||||||
|
storage_.GetAllocatedCapacity());
|
||||||
} else {
|
} else {
|
||||||
Destroy(storage_.GetInlinedData(), storage_.GetInlinedData() + size());
|
Destroy(storage_.GetInlinedData(), storage_.GetInlinedData() + size());
|
||||||
storage_.InitAllocation(new_allocation); // bug: only init once
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
storage_.SetAllocatedData(new_data);
|
||||||
|
storage_.SetAllocatedCapacity(new_capacity);
|
||||||
storage_.SetAllocatedSize(new_size);
|
storage_.SetAllocatedSize(new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -925,13 +934,13 @@ class InlinedVector {
|
||||||
new_capacity <<= 1;
|
new_capacity <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocation new_allocation(storage_.GetAllocator(), new_capacity);
|
pointer new_data =
|
||||||
|
AllocatorTraits::allocate(storage_.GetAllocator(), new_capacity);
|
||||||
|
|
||||||
UninitializedCopy(std::make_move_iterator(data()),
|
UninitializedCopy(std::make_move_iterator(data()),
|
||||||
std::make_move_iterator(data() + s),
|
std::make_move_iterator(data() + s), new_data);
|
||||||
new_allocation.buffer());
|
|
||||||
|
|
||||||
ResetAllocation(new_allocation, s);
|
ResetAllocation(new_data, new_capacity, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shift all elements from `position` to `end()` by `n` places to the right.
|
// Shift all elements from `position` to `end()` by `n` places to the right.
|
||||||
|
@ -957,15 +966,15 @@ class InlinedVector {
|
||||||
}
|
}
|
||||||
// Move everyone into the new allocation, leaving a gap of `n` for the
|
// Move everyone into the new allocation, leaving a gap of `n` for the
|
||||||
// requested shift.
|
// requested shift.
|
||||||
Allocation new_allocation(storage_.GetAllocator(), new_capacity);
|
pointer new_data =
|
||||||
|
AllocatorTraits::allocate(storage_.GetAllocator(), new_capacity);
|
||||||
size_type index = position - begin();
|
size_type index = position - begin();
|
||||||
UninitializedCopy(std::make_move_iterator(data()),
|
UninitializedCopy(std::make_move_iterator(data()),
|
||||||
std::make_move_iterator(data() + index),
|
std::make_move_iterator(data() + index), new_data);
|
||||||
new_allocation.buffer());
|
|
||||||
UninitializedCopy(std::make_move_iterator(data() + index),
|
UninitializedCopy(std::make_move_iterator(data() + index),
|
||||||
std::make_move_iterator(data() + s),
|
std::make_move_iterator(data() + s),
|
||||||
new_allocation.buffer() + index + n);
|
new_data + index + n);
|
||||||
ResetAllocation(new_allocation, s);
|
ResetAllocation(new_data, new_capacity, s);
|
||||||
|
|
||||||
// New allocation means our iterator is invalid, so we'll recalculate.
|
// New allocation means our iterator is invalid, so we'll recalculate.
|
||||||
// Since the entire gap is in new space, there's no used space to reuse.
|
// Since the entire gap is in new space, there's no used space to reuse.
|
||||||
|
@ -1005,23 +1014,25 @@ class InlinedVector {
|
||||||
assert(size() == capacity());
|
assert(size() == capacity());
|
||||||
const size_type s = size();
|
const size_type s = size();
|
||||||
|
|
||||||
Allocation new_allocation(storage_.GetAllocator(), 2 * capacity());
|
size_type new_capacity = 2 * capacity();
|
||||||
|
pointer new_data =
|
||||||
|
AllocatorTraits::allocate(storage_.GetAllocator(), new_capacity);
|
||||||
|
|
||||||
reference new_element =
|
reference new_element =
|
||||||
Construct(new_allocation.buffer() + s, std::forward<Args>(args)...);
|
Construct(new_data + s, std::forward<Args>(args)...);
|
||||||
UninitializedCopy(std::make_move_iterator(data()),
|
UninitializedCopy(std::make_move_iterator(data()),
|
||||||
std::make_move_iterator(data() + s),
|
std::make_move_iterator(data() + s), new_data);
|
||||||
new_allocation.buffer());
|
|
||||||
|
|
||||||
ResetAllocation(new_allocation, s + 1);
|
ResetAllocation(new_data, new_capacity, s + 1);
|
||||||
|
|
||||||
return new_element;
|
return new_element;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitAssign(size_type n) {
|
void InitAssign(size_type n) {
|
||||||
if (n > static_cast<size_type>(N)) {
|
if (n > static_cast<size_type>(N)) {
|
||||||
Allocation new_allocation(storage_.GetAllocator(), n);
|
pointer new_data = AllocatorTraits::allocate(storage_.GetAllocator(), n);
|
||||||
storage_.InitAllocation(new_allocation);
|
storage_.SetAllocatedData(new_data);
|
||||||
|
storage_.SetAllocatedCapacity(n);
|
||||||
UninitializedFill(storage_.GetAllocatedData(),
|
UninitializedFill(storage_.GetAllocatedData(),
|
||||||
storage_.GetAllocatedData() + n);
|
storage_.GetAllocatedData() + n);
|
||||||
storage_.SetAllocatedSize(n);
|
storage_.SetAllocatedSize(n);
|
||||||
|
@ -1034,8 +1045,9 @@ class InlinedVector {
|
||||||
|
|
||||||
void InitAssign(size_type n, const_reference v) {
|
void InitAssign(size_type n, const_reference v) {
|
||||||
if (n > static_cast<size_type>(N)) {
|
if (n > static_cast<size_type>(N)) {
|
||||||
Allocation new_allocation(storage_.GetAllocator(), n);
|
pointer new_data = AllocatorTraits::allocate(storage_.GetAllocator(), n);
|
||||||
storage_.InitAllocation(new_allocation);
|
storage_.SetAllocatedData(new_data);
|
||||||
|
storage_.SetAllocatedCapacity(n);
|
||||||
UninitializedFill(storage_.GetAllocatedData(),
|
UninitializedFill(storage_.GetAllocatedData(),
|
||||||
storage_.GetAllocatedData() + n, v);
|
storage_.GetAllocatedData() + n, v);
|
||||||
storage_.SetAllocatedSize(n);
|
storage_.SetAllocatedSize(n);
|
||||||
|
@ -1117,15 +1129,15 @@ class InlinedVector {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapImpl(InlinedVector& other) {
|
void SwapImpl(InlinedVector& other) {
|
||||||
using std::swap; // Augment ADL with `std::swap`.
|
using std::swap;
|
||||||
|
|
||||||
bool is_allocated = storage_.GetIsAllocated();
|
bool is_allocated = storage_.GetIsAllocated();
|
||||||
bool other_is_allocated = other.storage_.GetIsAllocated();
|
bool other_is_allocated = other.storage_.GetIsAllocated();
|
||||||
|
|
||||||
if (is_allocated && other_is_allocated) {
|
if (is_allocated && other_is_allocated) {
|
||||||
// Both out of line, so just swap the tag, allocation, and allocator.
|
// Both out of line, so just swap the tag, allocation, and allocator.
|
||||||
storage_.SwapSizeAndIsAllocated(other.storage_);
|
storage_.SwapSizeAndIsAllocated(std::addressof(other.storage_));
|
||||||
swap(storage_.GetAllocation(), other.storage_.GetAllocation());
|
storage_.SwapAllocatedSizeAndCapacity(std::addressof(other.storage_));
|
||||||
swap(storage_.GetAllocator(), other.storage_.GetAllocator());
|
swap(storage_.GetAllocator(), other.storage_.GetAllocator());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1155,7 +1167,7 @@ class InlinedVector {
|
||||||
a->Destroy(a->storage_.GetInlinedData() + b_size,
|
a->Destroy(a->storage_.GetInlinedData() + b_size,
|
||||||
a->storage_.GetInlinedData() + a_size);
|
a->storage_.GetInlinedData() + a_size);
|
||||||
|
|
||||||
storage_.SwapSizeAndIsAllocated(other.storage_);
|
storage_.SwapSizeAndIsAllocated(std::addressof(other.storage_));
|
||||||
swap(storage_.GetAllocator(), other.storage_.GetAllocator());
|
swap(storage_.GetAllocator(), other.storage_.GetAllocator());
|
||||||
|
|
||||||
assert(b->size() == a_size);
|
assert(b->size() == a_size);
|
||||||
|
@ -1183,11 +1195,11 @@ class InlinedVector {
|
||||||
static_cast<void>(b_size);
|
static_cast<void>(b_size);
|
||||||
|
|
||||||
// Made Local copies of `size()`, these can now be swapped
|
// Made Local copies of `size()`, these can now be swapped
|
||||||
a->storage_.SwapSizeAndIsAllocated(b->storage_);
|
a->storage_.SwapSizeAndIsAllocated(std::addressof(b->storage_));
|
||||||
|
|
||||||
// Copy `b_allocation` out before `b`'s union gets clobbered by
|
// Copy out before `b`'s union gets clobbered by `inline_space`
|
||||||
// `inline_space`
|
pointer b_data = b->storage_.GetAllocatedData();
|
||||||
Allocation b_allocation = b->storage_.GetAllocation();
|
size_type b_capacity = b->storage_.GetAllocatedCapacity();
|
||||||
|
|
||||||
b->UninitializedCopy(a->storage_.GetInlinedData(),
|
b->UninitializedCopy(a->storage_.GetInlinedData(),
|
||||||
a->storage_.GetInlinedData() + a_size,
|
a->storage_.GetInlinedData() + a_size,
|
||||||
|
@ -1195,7 +1207,8 @@ class InlinedVector {
|
||||||
a->Destroy(a->storage_.GetInlinedData(),
|
a->Destroy(a->storage_.GetInlinedData(),
|
||||||
a->storage_.GetInlinedData() + a_size);
|
a->storage_.GetInlinedData() + a_size);
|
||||||
|
|
||||||
a->storage_.GetAllocation() = b_allocation;
|
a->storage_.SetAllocatedData(b_data);
|
||||||
|
a->storage_.SetAllocatedCapacity(b_capacity);
|
||||||
|
|
||||||
if (a->storage_.GetAllocator() != b->storage_.GetAllocator()) {
|
if (a->storage_.GetAllocator() != b->storage_.GetAllocator()) {
|
||||||
swap(a->storage_.GetAllocator(), b->storage_.GetAllocator());
|
swap(a->storage_.GetAllocator(), b->storage_.GetAllocator());
|
||||||
|
|
|
@ -33,8 +33,6 @@ template <template <typename, size_t, typename> class InlinedVector, typename T,
|
||||||
size_t N, typename A>
|
size_t N, typename A>
|
||||||
class Storage<InlinedVector<T, N, A>> {
|
class Storage<InlinedVector<T, N, A>> {
|
||||||
public:
|
public:
|
||||||
class Allocation; // TODO(johnsoncj): Remove after migration
|
|
||||||
|
|
||||||
using allocator_type = A;
|
using allocator_type = A;
|
||||||
using value_type = typename allocator_type::value_type;
|
using value_type = typename allocator_type::value_type;
|
||||||
using pointer = typename allocator_type::pointer;
|
using pointer = typename allocator_type::pointer;
|
||||||
|
@ -48,6 +46,7 @@ class Storage<InlinedVector<T, N, A>> {
|
||||||
using const_iterator = const_pointer;
|
using const_iterator = const_pointer;
|
||||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
using AllocatorTraits = std::allocator_traits<allocator_type>;
|
||||||
|
|
||||||
explicit Storage(const allocator_type& alloc)
|
explicit Storage(const allocator_type& alloc)
|
||||||
: metadata_(alloc, /* empty and inlined */ 0) {}
|
: metadata_(alloc, /* empty and inlined */ 0) {}
|
||||||
|
@ -56,30 +55,25 @@ class Storage<InlinedVector<T, N, A>> {
|
||||||
|
|
||||||
bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; }
|
bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; }
|
||||||
|
|
||||||
Allocation& GetAllocation() {
|
|
||||||
return reinterpret_cast<Allocation&>(rep_.allocation_storage.allocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Allocation& GetAllocation() const {
|
|
||||||
return reinterpret_cast<const Allocation&>(
|
|
||||||
rep_.allocation_storage.allocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer GetInlinedData() {
|
pointer GetInlinedData() {
|
||||||
return reinterpret_cast<pointer>(
|
return reinterpret_cast<pointer>(
|
||||||
std::addressof(rep_.inlined_storage.inlined[0]));
|
std::addressof(data_.inlined.inlined_data[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
const_pointer GetInlinedData() const {
|
const_pointer GetInlinedData() const {
|
||||||
return reinterpret_cast<const_pointer>(
|
return reinterpret_cast<const_pointer>(
|
||||||
std::addressof(rep_.inlined_storage.inlined[0]));
|
std::addressof(data_.inlined.inlined_data[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer GetAllocatedData() { return GetAllocation().buffer(); }
|
pointer GetAllocatedData() { return data_.allocated.allocated_data; }
|
||||||
|
|
||||||
const_pointer GetAllocatedData() const { return GetAllocation().buffer(); }
|
const_pointer GetAllocatedData() const {
|
||||||
|
return data_.allocated.allocated_data;
|
||||||
|
}
|
||||||
|
|
||||||
size_type GetAllocatedCapacity() const { return GetAllocation().capacity(); }
|
size_type GetAllocatedCapacity() const {
|
||||||
|
return data_.allocated.allocated_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
allocator_type& GetAllocator() { return metadata_.template get<0>(); }
|
allocator_type& GetAllocator() { return metadata_.template get<0>(); }
|
||||||
|
|
||||||
|
@ -95,34 +89,23 @@ class Storage<InlinedVector<T, N, A>> {
|
||||||
|
|
||||||
void AddSize(size_type count) { GetSizeAndIsAllocated() += count << 1; }
|
void AddSize(size_type count) { GetSizeAndIsAllocated() += count << 1; }
|
||||||
|
|
||||||
void InitAllocation(const Allocation& allocation) {
|
void SetAllocatedData(pointer data) {
|
||||||
new (static_cast<void*>(std::addressof(rep_.allocation_storage.allocation)))
|
data_.allocated.allocated_data = data;
|
||||||
Allocation(allocation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapSizeAndIsAllocated(Storage& other) {
|
void SetAllocatedCapacity(size_type capacity) {
|
||||||
|
data_.allocated.allocated_capacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapSizeAndIsAllocated(Storage* other) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(GetSizeAndIsAllocated(), other.GetSizeAndIsAllocated());
|
swap(GetSizeAndIsAllocated(), other->GetSizeAndIsAllocated());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(johnsoncj): Make the below types private after migration
|
void SwapAllocatedSizeAndCapacity(Storage* other) {
|
||||||
class Allocation {
|
using std::swap;
|
||||||
size_type capacity_;
|
swap(data_.allocated, other->data_.allocated);
|
||||||
pointer buffer_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Allocation(allocator_type& a, size_type capacity)
|
|
||||||
: capacity_(capacity), buffer_(Create(a, capacity)) {}
|
|
||||||
void Dealloc(allocator_type& a) {
|
|
||||||
std::allocator_traits<allocator_type>::deallocate(a, buffer_, capacity_);
|
|
||||||
}
|
}
|
||||||
size_type capacity() const { return capacity_; }
|
|
||||||
const_pointer buffer() const { return buffer_; }
|
|
||||||
pointer buffer() { return buffer_; }
|
|
||||||
static pointer Create(allocator_type& a, size_type n) {
|
|
||||||
return std::allocator_traits<allocator_type>::allocate(a, n);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_type& GetSizeAndIsAllocated() { return metadata_.template get<1>(); }
|
size_type& GetSizeAndIsAllocated() { return metadata_.template get<1>(); }
|
||||||
|
@ -131,29 +114,27 @@ class Storage<InlinedVector<T, N, A>> {
|
||||||
return metadata_.template get<1>();
|
return metadata_.template get<1>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stores either the inlined or allocated representation
|
using Metadata =
|
||||||
union Rep {
|
container_internal::CompressedTuple<allocator_type, size_type>;
|
||||||
using ValueTypeBuffer =
|
|
||||||
|
struct Allocated {
|
||||||
|
pointer allocated_data;
|
||||||
|
size_type allocated_capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Inlined {
|
||||||
|
using InlinedDataElement =
|
||||||
absl::aligned_storage_t<sizeof(value_type), alignof(value_type)>;
|
absl::aligned_storage_t<sizeof(value_type), alignof(value_type)>;
|
||||||
using AllocationBuffer =
|
InlinedDataElement inlined_data[N];
|
||||||
absl::aligned_storage_t<sizeof(Allocation), alignof(Allocation)>;
|
|
||||||
|
|
||||||
// Structs wrap the buffers to perform indirection that solves a bizarre
|
|
||||||
// compilation error on Visual Studio (all known versions).
|
|
||||||
struct InlinedRep {
|
|
||||||
ValueTypeBuffer inlined[N];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AllocatedRep {
|
union Data {
|
||||||
AllocationBuffer allocation;
|
Allocated allocated;
|
||||||
|
Inlined inlined;
|
||||||
};
|
};
|
||||||
|
|
||||||
InlinedRep inlined_storage;
|
Metadata metadata_;
|
||||||
AllocatedRep allocation_storage;
|
Data data_;
|
||||||
};
|
|
||||||
|
|
||||||
container_internal::CompressedTuple<allocator_type, size_type> metadata_;
|
|
||||||
Rep rep_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace inlined_vector_internal
|
} // namespace inlined_vector_internal
|
||||||
|
|
|
@ -204,7 +204,7 @@ list(APPEND ABSL_MSVC_FLAGS
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND ABSL_MSVC_LINKOPTS
|
list(APPEND ABSL_MSVC_LINKOPTS
|
||||||
"/ignore:4221"
|
"-ignore:4221"
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND ABSL_MSVC_TEST_FLAGS
|
list(APPEND ABSL_MSVC_TEST_FLAGS
|
||||||
|
|
|
@ -205,7 +205,7 @@ ABSL_MSVC_FLAGS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
ABSL_MSVC_LINKOPTS = [
|
ABSL_MSVC_LINKOPTS = [
|
||||||
"/ignore:4221",
|
"-ignore:4221",
|
||||||
]
|
]
|
||||||
|
|
||||||
ABSL_MSVC_TEST_FLAGS = [
|
ABSL_MSVC_TEST_FLAGS = [
|
||||||
|
|
|
@ -189,6 +189,6 @@ COPT_VARS = {
|
||||||
MSVC_STYLE_EXCEPTIONS_FLAGS,
|
MSVC_STYLE_EXCEPTIONS_FLAGS,
|
||||||
"ABSL_MSVC_LINKOPTS": [
|
"ABSL_MSVC_LINKOPTS": [
|
||||||
# Object file doesn't export any previously undefined symbols
|
# Object file doesn't export any previously undefined symbols
|
||||||
"/ignore:4221",
|
"-ignore:4221",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue