diff options
-rw-r--r-- | absl/container/inlined_vector.h | 120 | ||||
-rw-r--r-- | absl/container/internal/inlined_vector.h | 44 | ||||
-rw-r--r-- | absl/debugging/BUILD.bazel | 1 | ||||
-rw-r--r-- | absl/debugging/CMakeLists.txt | 1 |
4 files changed, 87 insertions, 79 deletions
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index c31c319cc2a7..046182dda5b0 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -100,9 +100,8 @@ class InlinedVector { // InlinedVector Constructors and Destructor // --------------------------------------------------------------------------- - // Creates an empty inlined vector with a default initialized allocator. - InlinedVector() noexcept(noexcept(allocator_type())) - : storage_(allocator_type()) {} + // Creates an empty inlined vector with a value-initialized allocator. + InlinedVector() noexcept(noexcept(allocator_type())) : storage_() {} // Creates an empty inlined vector with a specified allocator. explicit InlinedVector(const allocator_type& alloc) noexcept @@ -112,22 +111,40 @@ class InlinedVector { explicit InlinedVector(size_type n, const allocator_type& alloc = allocator_type()) : 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`. InlinedVector(size_type n, const_reference v, const allocator_type& alloc = allocator_type()) : 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`. InlinedVector(std::initializer_list<value_type> list, const allocator_type& alloc = allocator_type()) - : storage_(alloc) { - AppendForwardRange(list.begin(), list.end()); - } + : InlinedVector(list.begin(), list.end(), alloc) {} // Creates an inlined vector with elements constructed from the provided // forward iterator range [`first`, `last`). @@ -140,7 +157,15 @@ class InlinedVector { InlinedVector(ForwardIterator first, ForwardIterator last, const allocator_type& alloc = allocator_type()) : 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 @@ -193,8 +218,8 @@ class InlinedVector { if (other.storage_.GetIsAllocated()) { // We can just steal the underlying buffer from the source. // That leaves the source empty, so we clear its size. - storage_.SetAllocatedData(other.storage_.GetAllocatedData()); - storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity()); + storage_.SetAllocatedData(other.storage_.GetAllocatedData(), + other.storage_.GetAllocatedCapacity()); storage_.SetAllocatedSize(other.size()); other.storage_.SetInlinedSize(0); } else { @@ -227,8 +252,8 @@ class InlinedVector { if (*storage_.GetAllocPtr() == *other.storage_.GetAllocPtr()) { // We can just steal the allocation from the source. storage_.SetAllocatedSize(other.size()); - storage_.SetAllocatedData(other.storage_.GetAllocatedData()); - storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity()); + storage_.SetAllocatedData(other.storage_.GetAllocatedData(), + other.storage_.GetAllocatedCapacity()); other.storage_.SetInlinedSize(0); } else { // We need to use our own allocator @@ -248,7 +273,7 @@ class InlinedVector { } } - ~InlinedVector() { clear(); } + ~InlinedVector() {} // --------------------------------------------------------------------------- // InlinedVector Member Accessors @@ -473,8 +498,8 @@ class InlinedVector { if (other.storage_.GetIsAllocated()) { clear(); storage_.SetAllocatedSize(other.size()); - storage_.SetAllocatedData(other.storage_.GetAllocatedData()); - storage_.SetAllocatedCapacity(other.storage_.GetAllocatedCapacity()); + storage_.SetAllocatedData(other.storage_.GetAllocatedData(), + other.storage_.GetAllocatedCapacity()); other.storage_.SetInlinedSize(0); } else { if (storage_.GetIsAllocated()) clear(); @@ -793,16 +818,8 @@ class InlinedVector { // Destroys all elements in the inlined vector, sets the size of `0` and // deallocates the heap allocation if the inlined vector was allocated. void clear() noexcept { - const bool is_allocated = storage_.GetIsAllocated(); - pointer the_data = - is_allocated ? storage_.GetAllocatedData() : storage_.GetInlinedData(); - inlined_vector_internal::DestroyElements(storage_.GetAllocPtr(), the_data, - storage_.GetSize()); + storage_.DestroyAndDeallocate(); storage_.SetInlinedSize(0); - if (is_allocated) { - AllocatorTraits::deallocate(*storage_.GetAllocPtr(), the_data, - storage_.GetAllocatedCapacity()); - } } // `InlinedVector::reserve()` @@ -883,8 +900,7 @@ class InlinedVector { Destroy(storage_.GetInlinedData(), storage_.GetInlinedData() + size()); } - storage_.SetAllocatedData(new_data); - storage_.SetAllocatedCapacity(new_capacity); + storage_.SetAllocatedData(new_data, new_capacity); storage_.SetAllocatedSize(new_size); } @@ -1032,53 +1048,6 @@ class InlinedVector { 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, const_reference v) { assert(position >= begin() && position <= end()); @@ -1191,8 +1160,7 @@ class InlinedVector { a->Destroy(a->storage_.GetInlinedData(), a->storage_.GetInlinedData() + a_size); - a->storage_.SetAllocatedData(b_data); - a->storage_.SetAllocatedCapacity(b_capacity); + a->storage_.SetAllocatedData(b_data, b_capacity); if (*a->storage_.GetAllocPtr() != *b->storage_.GetAllocPtr()) { swap(*a->storage_.GetAllocPtr(), *b->storage_.GetAllocPtr()); diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h index 79533a41f3d2..f4eb92ec169a 100644 --- a/absl/container/internal/inlined_vector.h +++ b/absl/container/internal/inlined_vector.h @@ -52,6 +52,16 @@ void DestroyElements(AllocatorType* alloc_ptr, ValueType* destroy_first, #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> class Storage { public: @@ -70,9 +80,15 @@ class Storage { using const_reverse_iterator = std::reverse_iterator<const_iterator>; using AllocatorTraits = absl::allocator_traits<allocator_type>; + using StorageView = inlined_vector_internal::StorageView<allocator_type>; + + Storage() : metadata_() {} + explicit Storage(const allocator_type& alloc) : metadata_(alloc, /* empty and inlined */ 0) {} + ~Storage() { DestroyAndDeallocate(); } + size_type GetSize() const { return GetSizeAndIsAllocated() >> 1; } bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; } @@ -97,6 +113,13 @@ class Storage { return data_.allocated.allocated_capacity; } + StorageView MakeStorageView() { + return GetIsAllocated() ? StorageView{GetAllocatedData(), GetSize(), + GetAllocatedCapacity()} + : StorageView{GetInlinedData(), GetSize(), + static_cast<size_type>(N)}; + } + allocator_type* GetAllocPtr() { return std::addressof(metadata_.template get<0>()); } @@ -113,9 +136,8 @@ class Storage { void AddSize(size_type count) { GetSizeAndIsAllocated() += count << 1; } - void SetAllocatedData(pointer data) { data_.allocated.allocated_data = data; } - - void SetAllocatedCapacity(size_type capacity) { + void SetAllocatedData(pointer data, size_type capacity) { + data_.allocated.allocated_data = data; data_.allocated.allocated_capacity = capacity; } @@ -129,6 +151,8 @@ class Storage { swap(data_.allocated, other->data_.allocated); } + void DestroyAndDeallocate(); + private: size_type& GetSizeAndIsAllocated() { return metadata_.template get<1>(); } @@ -159,6 +183,20 @@ class Storage { 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 absl diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel index e4aed5e4c47e..913cfafb2df6 100644 --- a/absl/debugging/BUILD.bazel +++ b/absl/debugging/BUILD.bazel @@ -61,6 +61,7 @@ cc_library( ":demangle_internal", "//absl/base", "//absl/base:core_headers", + "//absl/base:dynamic_annotations", "//absl/base:malloc_internal", ], ) diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt index d813fede60e0..001e27279049 100644 --- a/absl/debugging/CMakeLists.txt +++ b/absl/debugging/CMakeLists.txt @@ -50,6 +50,7 @@ absl_cc_library( absl::demangle_internal absl::base absl::core_headers + absl::dynamic_annotations absl::malloc_internal PUBLIC ) |