about summary refs log tree commit diff
path: root/absl/container/inlined_vector.h
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2019-06-18T20·05-0700
committerGennadiy Rozental <rogeeff@google.com>2019-06-18T20·10-0400
commit43ef2148c0936ebf7cb4be6b19927a9d9d145b8f (patch)
tree8a8ddca3da4d2f667ddfea48a736e80a147d5494 /absl/container/inlined_vector.h
parenta13d3df2b3ba68aeead92e2d078fba0510d55024 (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.h122
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()`