diff options
author | Abseil Team <absl-team@google.com> | 2019-01-07T17·01-0800 |
---|---|---|
committer | Shaindel Schwartz <shaindel@google.com> | 2019-01-07T20·22-0500 |
commit | b16aeb6756bdab08cdf12d40baab5b51f7d15b16 (patch) | |
tree | 5c5130ba335b32dd5df880fe4089bf847088b562 /absl/container/inlined_vector.h | |
parent | 7ffbe09f3d85504bd018783bbe1e2c12992fe47c (diff) |
Export of internal Abseil changes.
-- 5f1cf6547231f1b1daad6d1b785df6b0b999b3c9 by Samuel Benzaquen <sbenza@google.com>: Fix uninitialized member in the `iterator` class by using a union of the two possible states of the iterator. This silences a Wuninitialized warning in gcc>=7. PiperOrigin-RevId: 228175148 -- 98b4e3204c0ec3cfd4cb037e24d443ea4b63fc84 by CJ Johnson <johnsoncj@google.com>: Factors out the implementation of InlinedVector::swap(...) into a private member function PiperOrigin-RevId: 228173383 -- f1432ad3a8b05285c6d55bc4754cfae765485b7f by Abseil Team <absl-team@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 227891984 -- 03fc00c7a4efc6000e6d9125cb2e252bffda76fe by Andy Getzendanner <durandal@google.com>: Add a missing linebreak to a comment and markdownify two unordered lists. PiperOrigin-RevId: 227861389 -- 0d66c9afba4fc9aa52e61d9fb410e165018a7b48 by Abseil Team <absl-team@google.com>: Add an API to register a new source for the cycle clock. PiperOrigin-RevId: 227779218 -- 14d3f9b70c8818b8541e5fb2f6ca4c59d479de31 by Andy Getzendanner <durandal@google.com>: Correct a typo in a stripping marker. PiperOrigin-RevId: 227750014 -- 59df88740f4e315beb57a8772f8bcf7879440c74 by Matt Kulukundis <kfm@google.com>: Switch thread local handling to be more cross platform PiperOrigin-RevId: 227695133 -- 75deed5bfcb5c42534e933f104aa7d94e11e348d by Abseil Team <absl-team@google.com>: Rollback workaround toolchain bug for incorrect handling of thread_local in inline functions PiperOrigin-RevId: 227689133 -- 54994bf0afec026e6e0e7a199df0bbb4b7d9a4aa by Derek Mauro <dmauro@google.com>: Add -pthread to linkopts where it actually belongs, on the library that uses it. Fixes https://github.com/abseil/abseil-cpp/issues/240. PiperOrigin-RevId: 227612492 -- 893875f3536b7e0a1bad993aa6b2e083abb3b25a by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 227582833 -- 506c9b8e9002ca3389c7040473b68d4cbf94bdcc by Matt Kulukundis <kfm@google.com>: Workaround toolchain bug for incorrect handling of thread_local in inline functions PiperOrigin-RevId: 227561449 -- 29ee90d96dfe3114cf93f9bb92ea0cc9e768a407 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 227054634 GitOrigin-RevId: 5f1cf6547231f1b1daad6d1b785df6b0b999b3c9 Change-Id: Ibc90566d92ee6e0ad7e150f513ec7f5d22ec0a94
Diffstat (limited to 'absl/container/inlined_vector.h')
-rw-r--r-- | absl/container/inlined_vector.h | 151 |
1 files changed, 78 insertions, 73 deletions
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index fe228001bf2c..b6063441a0e9 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -795,79 +795,7 @@ class InlinedVector { void swap(InlinedVector& other) { if (ABSL_PREDICT_FALSE(this == &other)) return; - using std::swap; // Augment ADL with `std::swap`. - if (allocated() && other.allocated()) { - // Both out of line, so just swap the tag, allocation, and allocator. - swap(tag(), other.tag()); - swap(allocation(), other.allocation()); - swap(allocator(), other.allocator()); - return; - } - if (!allocated() && !other.allocated()) { - // Both inlined: swap up to smaller size, then move remaining elements. - InlinedVector* a = this; - InlinedVector* b = &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->inlined_space(), a->inlined_space() + b_size, - b->inlined_space()); - - // Move the remaining elements: - // [`b_size`, `a_size`) from `a` -> [`b_size`, `a_size`) from `b` - b->UninitializedCopy(a->inlined_space() + b_size, - a->inlined_space() + a_size, - b->inlined_space() + b_size); - a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size); - - swap(a->tag(), b->tag()); - swap(a->allocator(), b->allocator()); - 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 = &other; - if (a->allocated()) { - swap(a, b); - } - assert(!a->allocated()); - assert(b->allocated()); - 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()`, don't need `tag()` accurate anymore - swap(a->tag(), b->tag()); - - // Copy `b_allocation` out before `b`'s union gets clobbered by - // `inline_space` - Allocation b_allocation = b->allocation(); - - b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size, - b->inlined_space()); - a->Destroy(a->inlined_space(), a->inlined_space() + a_size); - - a->allocation() = b_allocation; - - if (a->allocator() != b->allocator()) { - swap(a->allocator(), b->allocator()); - } - - assert(b->size() == a_size); - assert(a->size() == b_size); + SwapImpl(other); } private: @@ -1238,6 +1166,83 @@ class InlinedVector { return begin() + index; } + void SwapImpl(InlinedVector& other) { + using std::swap; // Augment ADL with `std::swap`. + + if (allocated() && other.allocated()) { + // Both out of line, so just swap the tag, allocation, and allocator. + swap(tag(), other.tag()); + swap(allocation(), other.allocation()); + swap(allocator(), other.allocator()); + return; + } + if (!allocated() && !other.allocated()) { + // Both inlined: swap up to smaller size, then move remaining elements. + InlinedVector* a = this; + InlinedVector* b = &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->inlined_space(), a->inlined_space() + b_size, + b->inlined_space()); + + // Move the remaining elements: + // [`b_size`, `a_size`) from `a` -> [`b_size`, `a_size`) from `b` + b->UninitializedCopy(a->inlined_space() + b_size, + a->inlined_space() + a_size, + b->inlined_space() + b_size); + a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size); + + swap(a->tag(), b->tag()); + swap(a->allocator(), b->allocator()); + 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 = &other; + if (a->allocated()) { + swap(a, b); + } + assert(!a->allocated()); + assert(b->allocated()); + 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()`, don't need `tag()` accurate anymore + swap(a->tag(), b->tag()); + + // Copy `b_allocation` out before `b`'s union gets clobbered by + // `inline_space` + Allocation b_allocation = b->allocation(); + + b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size, + b->inlined_space()); + a->Destroy(a->inlined_space(), a->inlined_space() + a_size); + + a->allocation() = b_allocation; + + if (a->allocator() != b->allocator()) { + swap(a->allocator(), b->allocator()); + } + + assert(b->size() == a_size); + assert(a->size() == b_size); + } + // Stores either the inlined or allocated representation union Rep { using ValueTypeBuffer = |