Export of internal Abseil changes.
-- 39b55fafbe4a83f9f0524544a12d4ed02fdec751 by Xiaoyi Zhang <zhangxy@google.com>: Avoid -Wundef warning of macro `ABSL_HAVE_ELF_MEM_IMAGE`. This is github pull request https://github.com/abseil/abseil-cpp/pull/320. PiperOrigin-RevId: 251646785 -- 2fbf0de42d6723088211cb23444f16ecadcc7d67 by Abseil Team <absl-team@google.com>: Add missing dependency on base:dynamic_annotations. The target absl/debugging:symbolize includes dynamic_annotations from absl/debugging/symbolize_elf.inc. PiperOrigin-RevId: 251430877 -- 2537de6f01458938684f4818606ba5ce3f1c3cdf by CJ Johnson <johnsoncj@google.com>: In InlinedVector: Combines storage_.SetAllocatedData(...) and storage_.SetAllocatedCapacity(...) into a single two-arg function also called storage_.SetAllocatedData(...) such that data and capacity must always be set together PiperOrigin-RevId: 251331883 -- c05252c01710ac28d2c3defd09acfc55ecf2b8f1 by CJ Johnson <johnsoncj@google.com>: So that InlinedVector constructors do no leak allocations when throwing exceptions, this CL moves the call to `clear()` from `~InlinedVector()` to `~Storage()` In addition, noexcept specifiers have been added where appropriate (Copy construction and default construction on std::allocator are noexcept. See CppRef: https://en.cppreference.com/w/cpp/memory/allocator/allocator) PiperOrigin-RevId: 251256272 -- 34ce8367a8e29a0dea950c0e2967dd7cfdbd5d33 by CJ Johnson <johnsoncj@google.com>: Cleans up InlinedVector constructors by inlining Impl functions with only one caller and dispatching where appropriate PiperOrigin-RevId: 250919357 GitOrigin-RevId: 39b55fafbe4a83f9f0524544a12d4ed02fdec751 Change-Id: I21e8866582e6e02afb2c54f7347d624053e9ce45
This commit is contained in:
parent
bc9101f998
commit
61c9bf3e3e
4 changed files with 87 additions and 79 deletions
|
@ -100,9 +100,8 @@ class InlinedVector {
|
||||||
// InlinedVector Constructors and Destructor
|
// InlinedVector Constructors and Destructor
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Creates an empty inlined vector with a default initialized allocator.
|
// Creates an empty inlined vector with a value-initialized allocator.
|
||||||
InlinedVector() noexcept(noexcept(allocator_type()))
|
InlinedVector() noexcept(noexcept(allocator_type())) : storage_() {}
|
||||||
: storage_(allocator_type()) {}
|
|
||||||
|
|
||||||
// Creates an empty inlined vector with a specified allocator.
|
// Creates an empty inlined vector with a specified allocator.
|
||||||
explicit InlinedVector(const allocator_type& alloc) noexcept
|
explicit InlinedVector(const allocator_type& alloc) noexcept
|
||||||
|
@ -112,22 +111,40 @@ class InlinedVector {
|
||||||
explicit InlinedVector(size_type n,
|
explicit InlinedVector(size_type n,
|
||||||
const allocator_type& alloc = allocator_type())
|
const allocator_type& alloc = allocator_type())
|
||||||
: storage_(alloc) {
|
: storage_(alloc) {
|
||||||
InitAssign(n);
|
if (n > static_cast<size_type>(N)) {
|
||||||
|
pointer new_data = AllocatorTraits::allocate(*storage_.GetAllocPtr(), n);
|
||||||
|
storage_.SetAllocatedData(new_data, n);
|
||||||
|
UninitializedFill(storage_.GetAllocatedData(),
|
||||||
|
storage_.GetAllocatedData() + n);
|
||||||
|
storage_.SetAllocatedSize(n);
|
||||||
|
} else {
|
||||||
|
UninitializedFill(storage_.GetInlinedData(),
|
||||||
|
storage_.GetInlinedData() + n);
|
||||||
|
storage_.SetInlinedSize(n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an inlined vector with `n` copies of `v`.
|
// Creates an inlined vector with `n` copies of `v`.
|
||||||
InlinedVector(size_type n, const_reference v,
|
InlinedVector(size_type n, const_reference v,
|
||||||
const allocator_type& alloc = allocator_type())
|
const allocator_type& alloc = allocator_type())
|
||||||
: storage_(alloc) {
|
: storage_(alloc) {
|
||||||
InitAssign(n, v);
|
if (n > static_cast<size_type>(N)) {
|
||||||
|
pointer new_data = AllocatorTraits::allocate(*storage_.GetAllocPtr(), n);
|
||||||
|
storage_.SetAllocatedData(new_data, n);
|
||||||
|
UninitializedFill(storage_.GetAllocatedData(),
|
||||||
|
storage_.GetAllocatedData() + n, v);
|
||||||
|
storage_.SetAllocatedSize(n);
|
||||||
|
} else {
|
||||||
|
UninitializedFill(storage_.GetInlinedData(),
|
||||||
|
storage_.GetInlinedData() + n, v);
|
||||||
|
storage_.SetInlinedSize(n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an inlined vector of copies of the values in `list`.
|
// Creates an inlined vector of copies of the values in `list`.
|
||||||
InlinedVector(std::initializer_list<value_type> list,
|
InlinedVector(std::initializer_list<value_type> list,
|
||||||
const allocator_type& alloc = allocator_type())
|
const allocator_type& alloc = allocator_type())
|
||||||
: storage_(alloc) {
|
: InlinedVector(list.begin(), list.end(), alloc) {}
|
||||||
AppendForwardRange(list.begin(), list.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates an inlined vector with elements constructed from the provided
|
// Creates an inlined vector with elements constructed from the provided
|
||||||
// forward iterator range [`first`, `last`).
|
// forward iterator range [`first`, `last`).
|
||||||
|
@ -140,7 +157,15 @@ class InlinedVector {
|
||||||
InlinedVector(ForwardIterator first, ForwardIterator last,
|
InlinedVector(ForwardIterator first, ForwardIterator last,
|
||||||
const allocator_type& alloc = allocator_type())
|
const allocator_type& alloc = allocator_type())
|
||||||
: storage_(alloc) {
|
: storage_(alloc) {
|
||||||
AppendForwardRange(first, last);
|
auto length = std::distance(first, last);
|
||||||
|
reserve(size() + length);
|
||||||
|
if (storage_.GetIsAllocated()) {
|
||||||
|
UninitializedCopy(first, last, storage_.GetAllocatedData() + size());
|
||||||
|
storage_.SetAllocatedSize(size() + length);
|
||||||
|
} else {
|
||||||
|
UninitializedCopy(first, last, storage_.GetInlinedData() + size());
|
||||||
|
storage_.SetInlinedSize(size() + length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an inlined vector with elements constructed from the provided input
|
// Creates an inlined vector with elements constructed from the provided input
|
||||||
|
@ -193,8 +218,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_.SetAllocatedData(other.storage_.GetAllocatedData());
|
storage_.SetAllocatedData(other.storage_.GetAllocatedData(),
|
||||||
storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity());
|
other.storage_.GetAllocatedCapacity());
|
||||||
storage_.SetAllocatedSize(other.size());
|
storage_.SetAllocatedSize(other.size());
|
||||||
other.storage_.SetInlinedSize(0);
|
other.storage_.SetInlinedSize(0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -227,8 +252,8 @@ class InlinedVector {
|
||||||
if (*storage_.GetAllocPtr() == *other.storage_.GetAllocPtr()) {
|
if (*storage_.GetAllocPtr() == *other.storage_.GetAllocPtr()) {
|
||||||
// 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_.SetAllocatedData(other.storage_.GetAllocatedData());
|
storage_.SetAllocatedData(other.storage_.GetAllocatedData(),
|
||||||
storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity());
|
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
|
||||||
|
@ -248,7 +273,7 @@ class InlinedVector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~InlinedVector() { clear(); }
|
~InlinedVector() {}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// InlinedVector Member Accessors
|
// InlinedVector Member Accessors
|
||||||
|
@ -473,8 +498,8 @@ class InlinedVector {
|
||||||
if (other.storage_.GetIsAllocated()) {
|
if (other.storage_.GetIsAllocated()) {
|
||||||
clear();
|
clear();
|
||||||
storage_.SetAllocatedSize(other.size());
|
storage_.SetAllocatedSize(other.size());
|
||||||
storage_.SetAllocatedData(other.storage_.GetAllocatedData());
|
storage_.SetAllocatedData(other.storage_.GetAllocatedData(),
|
||||||
storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity());
|
other.storage_.GetAllocatedCapacity());
|
||||||
other.storage_.SetInlinedSize(0);
|
other.storage_.SetInlinedSize(0);
|
||||||
} else {
|
} else {
|
||||||
if (storage_.GetIsAllocated()) clear();
|
if (storage_.GetIsAllocated()) clear();
|
||||||
|
@ -793,16 +818,8 @@ class InlinedVector {
|
||||||
// Destroys all elements in the inlined vector, sets the size of `0` and
|
// Destroys all elements in the inlined vector, sets the size of `0` and
|
||||||
// deallocates the heap allocation if the inlined vector was allocated.
|
// deallocates the heap allocation if the inlined vector was allocated.
|
||||||
void clear() noexcept {
|
void clear() noexcept {
|
||||||
const bool is_allocated = storage_.GetIsAllocated();
|
storage_.DestroyAndDeallocate();
|
||||||
pointer the_data =
|
|
||||||
is_allocated ? storage_.GetAllocatedData() : storage_.GetInlinedData();
|
|
||||||
inlined_vector_internal::DestroyElements(storage_.GetAllocPtr(), the_data,
|
|
||||||
storage_.GetSize());
|
|
||||||
storage_.SetInlinedSize(0);
|
storage_.SetInlinedSize(0);
|
||||||
if (is_allocated) {
|
|
||||||
AllocatorTraits::deallocate(*storage_.GetAllocPtr(), the_data,
|
|
||||||
storage_.GetAllocatedCapacity());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// `InlinedVector::reserve()`
|
// `InlinedVector::reserve()`
|
||||||
|
@ -883,8 +900,7 @@ class InlinedVector {
|
||||||
Destroy(storage_.GetInlinedData(), storage_.GetInlinedData() + size());
|
Destroy(storage_.GetInlinedData(), storage_.GetInlinedData() + size());
|
||||||
}
|
}
|
||||||
|
|
||||||
storage_.SetAllocatedData(new_data);
|
storage_.SetAllocatedData(new_data, new_capacity);
|
||||||
storage_.SetAllocatedCapacity(new_capacity);
|
|
||||||
storage_.SetAllocatedSize(new_size);
|
storage_.SetAllocatedSize(new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1032,53 +1048,6 @@ class InlinedVector {
|
||||||
return new_element;
|
return new_element;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitAssign(size_type n) {
|
|
||||||
if (n > static_cast<size_type>(N)) {
|
|
||||||
pointer new_data = AllocatorTraits::allocate(*storage_.GetAllocPtr(), n);
|
|
||||||
storage_.SetAllocatedData(new_data);
|
|
||||||
storage_.SetAllocatedCapacity(n);
|
|
||||||
UninitializedFill(storage_.GetAllocatedData(),
|
|
||||||
storage_.GetAllocatedData() + n);
|
|
||||||
storage_.SetAllocatedSize(n);
|
|
||||||
} else {
|
|
||||||
UninitializedFill(storage_.GetInlinedData(),
|
|
||||||
storage_.GetInlinedData() + n);
|
|
||||||
storage_.SetInlinedSize(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitAssign(size_type n, const_reference v) {
|
|
||||||
if (n > static_cast<size_type>(N)) {
|
|
||||||
pointer new_data = AllocatorTraits::allocate(*storage_.GetAllocPtr(), n);
|
|
||||||
storage_.SetAllocatedData(new_data);
|
|
||||||
storage_.SetAllocatedCapacity(n);
|
|
||||||
UninitializedFill(storage_.GetAllocatedData(),
|
|
||||||
storage_.GetAllocatedData() + n, v);
|
|
||||||
storage_.SetAllocatedSize(n);
|
|
||||||
} else {
|
|
||||||
UninitializedFill(storage_.GetInlinedData(),
|
|
||||||
storage_.GetInlinedData() + n, v);
|
|
||||||
storage_.SetInlinedSize(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ForwardIt>
|
|
||||||
void AppendForwardRange(ForwardIt first, ForwardIt last) {
|
|
||||||
static_assert(absl::inlined_vector_internal::IsAtLeastForwardIterator<
|
|
||||||
ForwardIt>::value,
|
|
||||||
"");
|
|
||||||
|
|
||||||
auto length = std::distance(first, last);
|
|
||||||
reserve(size() + length);
|
|
||||||
if (storage_.GetIsAllocated()) {
|
|
||||||
UninitializedCopy(first, last, storage_.GetAllocatedData() + size());
|
|
||||||
storage_.SetAllocatedSize(size() + length);
|
|
||||||
} else {
|
|
||||||
UninitializedCopy(first, last, storage_.GetInlinedData() + size());
|
|
||||||
storage_.SetInlinedSize(size() + length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator InsertWithCount(const_iterator position, size_type n,
|
iterator InsertWithCount(const_iterator position, size_type n,
|
||||||
const_reference v) {
|
const_reference v) {
|
||||||
assert(position >= begin() && position <= end());
|
assert(position >= begin() && position <= end());
|
||||||
|
@ -1191,8 +1160,7 @@ class InlinedVector {
|
||||||
a->Destroy(a->storage_.GetInlinedData(),
|
a->Destroy(a->storage_.GetInlinedData(),
|
||||||
a->storage_.GetInlinedData() + a_size);
|
a->storage_.GetInlinedData() + a_size);
|
||||||
|
|
||||||
a->storage_.SetAllocatedData(b_data);
|
a->storage_.SetAllocatedData(b_data, b_capacity);
|
||||||
a->storage_.SetAllocatedCapacity(b_capacity);
|
|
||||||
|
|
||||||
if (*a->storage_.GetAllocPtr() != *b->storage_.GetAllocPtr()) {
|
if (*a->storage_.GetAllocPtr() != *b->storage_.GetAllocPtr()) {
|
||||||
swap(*a->storage_.GetAllocPtr(), *b->storage_.GetAllocPtr());
|
swap(*a->storage_.GetAllocPtr(), *b->storage_.GetAllocPtr());
|
||||||
|
|
|
@ -52,6 +52,16 @@ void DestroyElements(AllocatorType* alloc_ptr, ValueType* destroy_first,
|
||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename AllocatorType>
|
||||||
|
struct StorageView {
|
||||||
|
using pointer = typename AllocatorType::pointer;
|
||||||
|
using size_type = typename AllocatorType::size_type;
|
||||||
|
|
||||||
|
pointer data;
|
||||||
|
size_type size;
|
||||||
|
size_type capacity;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, size_t N, typename A>
|
template <typename T, size_t N, typename A>
|
||||||
class Storage {
|
class Storage {
|
||||||
public:
|
public:
|
||||||
|
@ -70,9 +80,15 @@ class Storage {
|
||||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
using AllocatorTraits = absl::allocator_traits<allocator_type>;
|
using AllocatorTraits = absl::allocator_traits<allocator_type>;
|
||||||
|
|
||||||
|
using StorageView = inlined_vector_internal::StorageView<allocator_type>;
|
||||||
|
|
||||||
|
Storage() : metadata_() {}
|
||||||
|
|
||||||
explicit Storage(const allocator_type& alloc)
|
explicit Storage(const allocator_type& alloc)
|
||||||
: metadata_(alloc, /* empty and inlined */ 0) {}
|
: metadata_(alloc, /* empty and inlined */ 0) {}
|
||||||
|
|
||||||
|
~Storage() { DestroyAndDeallocate(); }
|
||||||
|
|
||||||
size_type GetSize() const { return GetSizeAndIsAllocated() >> 1; }
|
size_type GetSize() const { return GetSizeAndIsAllocated() >> 1; }
|
||||||
|
|
||||||
bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; }
|
bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; }
|
||||||
|
@ -97,6 +113,13 @@ class Storage {
|
||||||
return data_.allocated.allocated_capacity;
|
return data_.allocated.allocated_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StorageView MakeStorageView() {
|
||||||
|
return GetIsAllocated() ? StorageView{GetAllocatedData(), GetSize(),
|
||||||
|
GetAllocatedCapacity()}
|
||||||
|
: StorageView{GetInlinedData(), GetSize(),
|
||||||
|
static_cast<size_type>(N)};
|
||||||
|
}
|
||||||
|
|
||||||
allocator_type* GetAllocPtr() {
|
allocator_type* GetAllocPtr() {
|
||||||
return std::addressof(metadata_.template get<0>());
|
return std::addressof(metadata_.template get<0>());
|
||||||
}
|
}
|
||||||
|
@ -113,9 +136,8 @@ class Storage {
|
||||||
|
|
||||||
void AddSize(size_type count) { GetSizeAndIsAllocated() += count << 1; }
|
void AddSize(size_type count) { GetSizeAndIsAllocated() += count << 1; }
|
||||||
|
|
||||||
void SetAllocatedData(pointer data) { data_.allocated.allocated_data = data; }
|
void SetAllocatedData(pointer data, size_type capacity) {
|
||||||
|
data_.allocated.allocated_data = data;
|
||||||
void SetAllocatedCapacity(size_type capacity) {
|
|
||||||
data_.allocated.allocated_capacity = capacity;
|
data_.allocated.allocated_capacity = capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +151,8 @@ class Storage {
|
||||||
swap(data_.allocated, other->data_.allocated);
|
swap(data_.allocated, other->data_.allocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DestroyAndDeallocate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_type& GetSizeAndIsAllocated() { return metadata_.template get<1>(); }
|
size_type& GetSizeAndIsAllocated() { return metadata_.template get<1>(); }
|
||||||
|
|
||||||
|
@ -159,6 +183,20 @@ class Storage {
|
||||||
Data data_;
|
Data data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T, size_t N, typename A>
|
||||||
|
void Storage<T, N, A>::DestroyAndDeallocate() {
|
||||||
|
namespace ivi = inlined_vector_internal;
|
||||||
|
|
||||||
|
StorageView storage_view = MakeStorageView();
|
||||||
|
|
||||||
|
ivi::DestroyElements(GetAllocPtr(), storage_view.data, storage_view.size);
|
||||||
|
|
||||||
|
if (GetIsAllocated()) {
|
||||||
|
AllocatorTraits::deallocate(*GetAllocPtr(), storage_view.data,
|
||||||
|
storage_view.capacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace inlined_vector_internal
|
} // namespace inlined_vector_internal
|
||||||
} // namespace absl
|
} // namespace absl
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ cc_library(
|
||||||
":demangle_internal",
|
":demangle_internal",
|
||||||
"//absl/base",
|
"//absl/base",
|
||||||
"//absl/base:core_headers",
|
"//absl/base:core_headers",
|
||||||
|
"//absl/base:dynamic_annotations",
|
||||||
"//absl/base:malloc_internal",
|
"//absl/base:malloc_internal",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -50,6 +50,7 @@ absl_cc_library(
|
||||||
absl::demangle_internal
|
absl::demangle_internal
|
||||||
absl::base
|
absl::base
|
||||||
absl::core_headers
|
absl::core_headers
|
||||||
|
absl::dynamic_annotations
|
||||||
absl::malloc_internal
|
absl::malloc_internal
|
||||||
PUBLIC
|
PUBLIC
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue