diff options
author | Abseil Team <absl-team@google.com> | 2019-06-27 17:24:26 -0700 |
---|---|---|
committer | Shaindel Schwartz <shaindel@google.com> | 2019-06-28 11:37:15 -0400 |
commit | c964fcffac27bd4a9ff67fe393410dd1146ef8b8 (patch) | |
tree | 3ff13a27c0de86de82d898933e808d4b7f69f823 /absl/container/inlined_vector.h | |
parent | 72e09a54d993b192db32be14c65adf7e9bd08c31 (diff) |
Export of internal Abseil changes.
--
c321829735accc2e6beb81e6a5a4421e5647b876 by CJ Johnson <johnsoncj@google.com>:
Updates the definition of InlinedVector::swap(InlinedVector&) to be exception safe and adds exception safety tests
PiperOrigin-RevId: 255511536
--
0d86445891748efb09430eb9ede267b54185a246 by CJ Johnson <johnsoncj@google.com>:
Updates the definition of InlinedVector::erase(...) to be exception safe and adds an exception safety test for it.
PiperOrigin-RevId: 255492671
--
f07e8fa62dfe9eb0d025b27fca8c6db43c5a328f by CJ Johnson <johnsoncj@google.com>:
Updates the implementation of InlinedVector::emplace_back(...) to be exception safe and adds exception safety tests
PiperOrigin-RevId: 255422837
--
4c3be92bfe4c1636a03cef8fd5aa802fed0d2c61 by Abseil Team <absl-team@google.com>:
Internal Change
PiperOrigin-RevId: 255422693
--
6df38ea42f00678c357a539016163f8ac4c084e6 by Gennadiy Rozental <rogeeff@google.com>:
Introduce public interfaces for setting and getting program usage messages.
PiperOrigin-RevId: 255291467
--
8f21d594aed3971d37db70226847c693eb548edb by Laramie Leavitt <lar@google.com>:
Move absl/random's copy of ABSL_ATTRIBUTE_FORCE_INLINE and
ABSL_ATTRIBUTE_NEVER_INLINE into .cc files and rename to
prevent conflicts.
https://github.com/abseil/abseil-cpp/issues/343
PiperOrigin-RevId: 255288599
--
6b7430ad0c8bd860fb9394894f5eeedd1acc9f77 by CJ Johnson <johnsoncj@google.com>:
Updates the ScopedAllocatorWorks test for InlinedVector to not rely on the byte count allocated by the standard library
In doing so, removes LegacyNextCapacityFrom(...) impl function from InlinedVector
Also applies clang-format to the test file
PiperOrigin-RevId: 255207606
GitOrigin-RevId: c321829735accc2e6beb81e6a5a4421e5647b876
Change-Id: I7438211c36c4549fca2e866658f8d579c65d7d52
Diffstat (limited to 'absl/container/inlined_vector.h')
-rw-r--r-- | absl/container/inlined_vector.h | 142 |
1 files changed, 9 insertions, 133 deletions
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index e67885c2..7552723d 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -640,28 +640,7 @@ class InlinedVector { // returning a `reference` to the emplaced element. template <typename... Args> reference emplace_back(Args&&... args) { - size_type s = size(); - if (ABSL_PREDICT_FALSE(s == capacity())) { - size_type new_capacity = 2 * capacity(); - pointer new_data = - AllocatorTraits::allocate(*storage_.GetAllocPtr(), new_capacity); - reference new_element = - Construct(new_data + s, std::forward<Args>(args)...); - UninitializedCopy(std::make_move_iterator(data()), - std::make_move_iterator(data() + s), new_data); - ResetAllocation(new_data, new_capacity, s + 1); - return new_element; - } else { - pointer space; - if (storage_.GetIsAllocated()) { - storage_.SetAllocatedSize(s + 1); - space = storage_.GetAllocatedData(); - } else { - storage_.SetInlinedSize(s + 1); - space = storage_.GetInlinedData(); - } - return Construct(space + s, std::forward<Args>(args)...); - } + return storage_.EmplaceBack(std::forward<Args>(args)...); } // `InlinedVector::push_back()` @@ -696,10 +675,7 @@ class InlinedVector { assert(pos >= begin()); assert(pos < end()); - iterator position = const_cast<iterator>(pos); - std::move(position + 1, end(), position); - pop_back(); - return position; + return storage_.Erase(pos, pos + 1); } // Overload of `InlinedVector::erase()` for erasing all elements in the @@ -707,28 +683,15 @@ class InlinedVector { // to the first element following the range erased or the end iterator if `to` // was the end iterator. iterator erase(const_iterator from, const_iterator to) { - assert(begin() <= from); + assert(from >= begin()); assert(from <= to); assert(to <= end()); - iterator range_start = const_cast<iterator>(from); - iterator range_end = const_cast<iterator>(to); - - size_type s = size(); - ptrdiff_t erase_gap = std::distance(range_start, range_end); - if (erase_gap > 0) { - pointer space; - if (storage_.GetIsAllocated()) { - space = storage_.GetAllocatedData(); - storage_.SetAllocatedSize(s - erase_gap); - } else { - space = storage_.GetInlinedData(); - storage_.SetInlinedSize(s - erase_gap); - } - std::move(range_end, space + s, range_start); - Destroy(space + s - erase_gap, space + s); + if (ABSL_PREDICT_TRUE(from != to)) { + return storage_.Erase(from, to); + } else { + return const_cast<iterator>(from); } - return range_start; } // `InlinedVector::clear()` @@ -774,96 +737,9 @@ class InlinedVector { // // Swaps the contents of this inlined vector with the contents of `other`. void swap(InlinedVector& other) { - using std::swap; - - if (ABSL_PREDICT_FALSE(this == std::addressof(other))) { - return; - } - - bool is_allocated = storage_.GetIsAllocated(); - bool other_is_allocated = other.storage_.GetIsAllocated(); - - if (is_allocated && other_is_allocated) { - // Both out of line, so just swap the tag, allocation, and allocator. - storage_.SwapSizeAndIsAllocated(std::addressof(other.storage_)); - storage_.SwapAllocatedSizeAndCapacity(std::addressof(other.storage_)); - swap(*storage_.GetAllocPtr(), *other.storage_.GetAllocPtr()); - - return; - } - - if (!is_allocated && !other_is_allocated) { - // Both inlined: swap up to smaller size, then move remaining elements. - InlinedVector* a = this; - InlinedVector* b = std::addressof(other); - if (size() < other.size()) { - swap(a, b); - } - - const size_type a_size = a->size(); - const size_type b_size = b->size(); - assert(a_size >= b_size); - // `a` is larger. Swap the elements up to the smaller array size. - std::swap_ranges(a->storage_.GetInlinedData(), - a->storage_.GetInlinedData() + b_size, - b->storage_.GetInlinedData()); - - // Move the remaining elements: - // [`b_size`, `a_size`) from `a` -> [`b_size`, `a_size`) from `b` - b->UninitializedCopy(a->storage_.GetInlinedData() + b_size, - a->storage_.GetInlinedData() + a_size, - b->storage_.GetInlinedData() + b_size); - a->Destroy(a->storage_.GetInlinedData() + b_size, - a->storage_.GetInlinedData() + a_size); - - storage_.SwapSizeAndIsAllocated(std::addressof(other.storage_)); - swap(*storage_.GetAllocPtr(), *other.storage_.GetAllocPtr()); - - assert(b->size() == a_size); - assert(a->size() == b_size); - return; - } - - // One is out of line, one is inline. - // We first move the elements from the inlined vector into the - // inlined space in the other vector. We then put the other vector's - // pointer/capacity into the originally inlined vector and swap - // the tags. - InlinedVector* a = this; - InlinedVector* b = std::addressof(other); - if (a->storage_.GetIsAllocated()) { - swap(a, b); - } - - assert(!a->storage_.GetIsAllocated()); - assert(b->storage_.GetIsAllocated()); - - const size_type a_size = a->size(); - const size_type b_size = b->size(); - // In an optimized build, `b_size` would be unused. - static_cast<void>(b_size); - - // Made Local copies of `size()`, these can now be swapped - a->storage_.SwapSizeAndIsAllocated(std::addressof(b->storage_)); - - // Copy out before `b`'s union gets clobbered by `inline_space` - pointer b_data = b->storage_.GetAllocatedData(); - size_type b_capacity = b->storage_.GetAllocatedCapacity(); - - b->UninitializedCopy(a->storage_.GetInlinedData(), - a->storage_.GetInlinedData() + a_size, - b->storage_.GetInlinedData()); - a->Destroy(a->storage_.GetInlinedData(), - a->storage_.GetInlinedData() + a_size); - - a->storage_.SetAllocatedData(b_data, b_capacity); - - if (*a->storage_.GetAllocPtr() != *b->storage_.GetAllocPtr()) { - swap(*a->storage_.GetAllocPtr(), *b->storage_.GetAllocPtr()); + if (ABSL_PREDICT_TRUE(this != std::addressof(other))) { + storage_.Swap(std::addressof(other.storage_)); } - - assert(b->size() == a_size); - assert(a->size() == b_size); } private: |