diff options
author | Abseil Team <absl-team@google.com> | 2019-06-18T20·05-0700 |
---|---|---|
committer | Gennadiy Rozental <rogeeff@google.com> | 2019-06-18T20·10-0400 |
commit | 43ef2148c0936ebf7cb4be6b19927a9d9d145b8f (patch) | |
tree | 8a8ddca3da4d2f667ddfea48a736e80a147d5494 /absl/container/inlined_vector.h | |
parent | a13d3df2b3ba68aeead92e2d078fba0510d55024 (diff) |
Export of internal Abseil changes.
-- 635146be541d732fbf2e9c93c6bec89035552484 by Gennadiy Rozental <rogeeff@google.com>: Merge external PR #324 PiperOrigin-RevId: 253849839 -- 7a37f87f0f419ab535e59c7dae7961546586671a by Gennadiy Rozental <rogeeff@google.com>: Merge external PR #323 PiperOrigin-RevId: 253849558 -- 75455e93e1f3987c926f35fbe80a0ea84e4ba35b by CJ Johnson <johnsoncj@google.com>: Removes `ivi` namespace typedef to reduce reader confusion PiperOrigin-RevId: 253789534 -- 2f99d27194468129767c48ab621b952660427493 by CJ Johnson <johnsoncj@google.com>: New benchmarks the various overloads of InlinedVector::assign(...)/InlinedVector::operator=(...) PiperOrigin-RevId: 253787316 -- a0949eb100b93aae22b85b4a4820e4bf9a5a2dbb by CJ Johnson <johnsoncj@google.com>: Updates the definition of `InlinedVector::pop_back(...)` to be cleaner and more direct (hiding the is_allocated branch behind a single call to `data()`) Adds exception safety test for `InlinedVector::pop_back(...)` PiperOrigin-RevId: 253607385 -- 2dbc728ddf84835dcb6341f9a166f1c9bde103b9 by CJ Johnson <johnsoncj@google.com>: Adds the remaining constructor exception safety tests for InlinedVector PiperOrigin-RevId: 253592324 -- 40d88e0d6232c93af5e008088f69ad41cb44e4ce by CJ Johnson <johnsoncj@google.com>: Updates the constructors of InlinedVector to new, exception-safe and more-performant implementations. PiperOrigin-RevId: 253294508 GitOrigin-RevId: 635146be541d732fbf2e9c93c6bec89035552484 Change-Id: I7d37a749632084f5d7fa56d42392e622a9d0180d
Diffstat (limited to 'absl/container/inlined_vector.h')
-rw-r--r-- | absl/container/inlined_vector.h | 122 |
1 files changed, 42 insertions, 80 deletions
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index 046182dda5b0..2c96cc37b47a 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -70,7 +70,16 @@ class InlinedVector { N > 0, "InlinedVector cannot be instantiated with `0` inlined elements."); using Storage = inlined_vector_internal::Storage<T, N, A>; + using rvalue_reference = typename Storage::rvalue_reference; + using MoveIterator = typename Storage::MoveIterator; using AllocatorTraits = typename Storage::AllocatorTraits; + using IsMemcpyOk = typename Storage::IsMemcpyOk; + + template <typename Iterator> + using IteratorValueAdapter = + typename Storage::template IteratorValueAdapter<Iterator>; + using CopyValueAdapter = typename Storage::CopyValueAdapter; + using DefaultValueAdapter = typename Storage::DefaultValueAdapter; template <typename Iterator> using EnableIfAtLeastForwardIterator = absl::enable_if_t< @@ -80,8 +89,6 @@ class InlinedVector { using DisableIfAtLeastForwardIterator = absl::enable_if_t< !inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value>; - using rvalue_reference = typename Storage::rvalue_reference; - public: using allocator_type = typename Storage::allocator_type; using value_type = typename Storage::value_type; @@ -111,34 +118,14 @@ class InlinedVector { explicit InlinedVector(size_type n, const allocator_type& alloc = allocator_type()) : storage_(alloc) { - 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); - } + storage_.Initialize(DefaultValueAdapter(), 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) { - 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); - } + storage_.Initialize(CopyValueAdapter(v), n); } // Creates an inlined vector of copies of the values in `list`. @@ -157,15 +144,8 @@ class InlinedVector { InlinedVector(ForwardIterator first, ForwardIterator last, const allocator_type& alloc = allocator_type()) : storage_(alloc) { - 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); - } + storage_.Initialize(IteratorValueAdapter<ForwardIterator>(first), + std::distance(first, last)); } // Creates an inlined vector with elements constructed from the provided input @@ -185,14 +165,11 @@ class InlinedVector { // Creates a copy of an `other` inlined vector using a specified allocator. InlinedVector(const InlinedVector& other, const allocator_type& alloc) : storage_(alloc) { - reserve(other.size()); - if (storage_.GetIsAllocated()) { - UninitializedCopy(other.begin(), other.end(), - storage_.GetAllocatedData()); - storage_.SetAllocatedSize(other.size()); + if (IsMemcpyOk::value && !other.storage_.GetIsAllocated()) { + storage_.MemcpyContents(other.storage_); } else { - UninitializedCopy(other.begin(), other.end(), storage_.GetInlinedData()); - storage_.SetInlinedSize(other.size()); + storage_.Initialize(IteratorValueAdapter<const_pointer>(other.data()), + other.size()); } } @@ -215,20 +192,21 @@ class InlinedVector { absl::allocator_is_nothrow<allocator_type>::value || std::is_nothrow_move_constructible<value_type>::value) : storage_(*other.storage_.GetAllocPtr()) { - if (other.storage_.GetIsAllocated()) { - // We can just steal the underlying buffer from the source. - // That leaves the source empty, so we clear its size. + if (IsMemcpyOk::value) { + storage_.MemcpyContents(other.storage_); + other.storage_.SetInlinedSize(0); + } else if (other.storage_.GetIsAllocated()) { storage_.SetAllocatedData(other.storage_.GetAllocatedData(), other.storage_.GetAllocatedCapacity()); - storage_.SetAllocatedSize(other.size()); + storage_.SetAllocatedSize(other.storage_.GetSize()); other.storage_.SetInlinedSize(0); } else { - UninitializedCopy( - std::make_move_iterator(other.storage_.GetInlinedData()), - std::make_move_iterator(other.storage_.GetInlinedData() + - other.size()), - storage_.GetInlinedData()); - storage_.SetInlinedSize(other.size()); + IteratorValueAdapter<MoveIterator> other_values( + MoveIterator(other.storage_.GetInlinedData())); + inlined_vector_internal::ConstructElements( + storage_.GetAllocPtr(), storage_.GetInlinedData(), &other_values, + other.storage_.GetSize()); + storage_.SetInlinedSize(other.storage_.GetSize()); } } @@ -248,28 +226,19 @@ class InlinedVector { InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept( absl::allocator_is_nothrow<allocator_type>::value) : storage_(alloc) { - if (other.storage_.GetIsAllocated()) { - if (*storage_.GetAllocPtr() == *other.storage_.GetAllocPtr()) { - // We can just steal the allocation from the source. - storage_.SetAllocatedSize(other.size()); - storage_.SetAllocatedData(other.storage_.GetAllocatedData(), - other.storage_.GetAllocatedCapacity()); - other.storage_.SetInlinedSize(0); - } else { - // We need to use our own allocator - reserve(other.size()); - UninitializedCopy(std::make_move_iterator(other.begin()), - std::make_move_iterator(other.end()), - storage_.GetAllocatedData()); - storage_.SetAllocatedSize(other.size()); - } + if (IsMemcpyOk::value) { + storage_.MemcpyContents(other.storage_); + other.storage_.SetInlinedSize(0); + } else if ((*storage_.GetAllocPtr() == *other.storage_.GetAllocPtr()) && + other.storage_.GetIsAllocated()) { + storage_.SetAllocatedData(other.storage_.GetAllocatedData(), + other.storage_.GetAllocatedCapacity()); + storage_.SetAllocatedSize(other.storage_.GetSize()); + other.storage_.SetInlinedSize(0); } else { - UninitializedCopy( - std::make_move_iterator(other.storage_.GetInlinedData()), - std::make_move_iterator(other.storage_.GetInlinedData() + - other.size()), - storage_.GetInlinedData()); - storage_.SetInlinedSize(other.size()); + storage_.Initialize( + IteratorValueAdapter<MoveIterator>(MoveIterator(other.data())), + other.size()); } } @@ -757,15 +726,8 @@ class InlinedVector { // by `1` (unless the inlined vector is empty, in which case this is a no-op). void pop_back() noexcept { assert(!empty()); - size_type s = size(); - if (storage_.GetIsAllocated()) { - Destroy(storage_.GetAllocatedData() + s - 1, - storage_.GetAllocatedData() + s); - storage_.SetAllocatedSize(s - 1); - } else { - Destroy(storage_.GetInlinedData() + s - 1, storage_.GetInlinedData() + s); - storage_.SetInlinedSize(s - 1); - } + AllocatorTraits::destroy(*storage_.GetAllocPtr(), data() + (size() - 1)); + storage_.AddSize(-1); } // `InlinedVector::erase()` |