Changes imported from Abseil "staging" branch:
- f679f7de2957ac4dca0a862d04f1165d2f503525 Merge GitHub PR #78: Fix typo in thread_identity.h by Derek Mauro <dmauro@google.com> - 369cbefc9ebb8503e3c25b1516c856dab3bed7ac Minor refactor of operator-(uint128). by Alex Strelnikov <strel@google.com> - fba0f8c33b051d90936ad0fcaa4bea83f554bf8d Merge GitHub PR #75: Fix typo in per_thread_tls.h by Derek Mauro <dmauro@google.com> - 76d5d25a54ab93c1ea3bc74b5a28ba335b0f2bab Implement InlinedVector::shrink_to_fit() method. by Abseil Team <absl-team@google.com> GitOrigin-RevId: f679f7de2957ac4dca0a862d04f1165d2f503525 Change-Id: I03b39fdbd70c00a455d98d949d413dd7c8019578
This commit is contained in:
		
							parent
							
								
									98bff8b2bc
								
							
						
					
					
						commit
						c742b72354
					
				
					 3 changed files with 117 additions and 7 deletions
				
			
		|  | @ -573,6 +573,42 @@ class InlinedVector { | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   // InlinedVector::shrink_to_fit()
 | ||||||
|  |   //
 | ||||||
|  |   // Reduces memory usage by freeing unused memory.
 | ||||||
|  |   // After this call `capacity()` will be equal to `max(N, size())`.
 | ||||||
|  |   //
 | ||||||
|  |   // If `size() <= N` and the elements are currently stored on the heap, they
 | ||||||
|  |   // will be moved to the inlined storage and the heap memory deallocated.
 | ||||||
|  |   // If `size() > N` and `size() < capacity()` the elements will be moved to
 | ||||||
|  |   // a reallocated storage on heap.
 | ||||||
|  |   void shrink_to_fit() { | ||||||
|  |     const auto s = size(); | ||||||
|  |     if (!allocated() || s == capacity()) { | ||||||
|  |       // There's nothing to deallocate.
 | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (s <= N) { | ||||||
|  |       // Move the elements to the inlined storage.
 | ||||||
|  |       // We have to do this using a temporary, because inlined_storage and
 | ||||||
|  |       // allocation_storage are in a union field.
 | ||||||
|  |       auto temp = std::move(*this); | ||||||
|  |       assign(std::make_move_iterator(temp.begin()), | ||||||
|  |              std::make_move_iterator(temp.end())); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Reallocate storage and move elements.
 | ||||||
|  |     // We can't simply use the same approach as above, because assign() would
 | ||||||
|  |     // call into reserve() internally and reserve larger capacity than we need.
 | ||||||
|  |     Allocation new_allocation(allocator(), s); | ||||||
|  |     UninitializedCopy(std::make_move_iterator(allocated_space()), | ||||||
|  |                       std::make_move_iterator(allocated_space() + s), | ||||||
|  |                       new_allocation.buffer()); | ||||||
|  |     ResetAllocation(new_allocation, s); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   // InlinedVector::swap()
 |   // InlinedVector::swap()
 | ||||||
|   //
 |   //
 | ||||||
|   // Swaps the contents of this inlined vector with the contents of `other`.
 |   // Swaps the contents of this inlined vector with the contents of `other`.
 | ||||||
|  |  | ||||||
|  | @ -407,6 +407,69 @@ TEST(InlinedVectorTest, EmplaceBack) { | ||||||
|   EXPECT_EQ(allocated_element.second, 1729); |   EXPECT_EQ(allocated_element.second, 1729); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | TEST(InlinedVectorTest, ShrinkToFitGrowingVector) { | ||||||
|  |   absl::InlinedVector<std::pair<std::string, int>, 1> v; | ||||||
|  | 
 | ||||||
|  |   v.shrink_to_fit(); | ||||||
|  |   EXPECT_EQ(v.capacity(), 1); | ||||||
|  | 
 | ||||||
|  |   v.emplace_back("answer", 42); | ||||||
|  |   v.shrink_to_fit(); | ||||||
|  |   EXPECT_EQ(v.capacity(), 1); | ||||||
|  | 
 | ||||||
|  |   v.emplace_back("taxicab", 1729); | ||||||
|  |   EXPECT_GE(v.capacity(), 2); | ||||||
|  |   v.shrink_to_fit(); | ||||||
|  |   EXPECT_EQ(v.capacity(), 2); | ||||||
|  | 
 | ||||||
|  |   v.reserve(100); | ||||||
|  |   EXPECT_GE(v.capacity(), 100); | ||||||
|  |   v.shrink_to_fit(); | ||||||
|  |   EXPECT_EQ(v.capacity(), 2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TEST(InlinedVectorTest, ShrinkToFitEdgeCases) { | ||||||
|  |   { | ||||||
|  |     absl::InlinedVector<std::pair<std::string, int>, 1> v; | ||||||
|  |     v.emplace_back("answer", 42); | ||||||
|  |     v.emplace_back("taxicab", 1729); | ||||||
|  |     EXPECT_GE(v.capacity(), 2); | ||||||
|  |     v.pop_back(); | ||||||
|  |     v.shrink_to_fit(); | ||||||
|  |     EXPECT_EQ(v.capacity(), 1); | ||||||
|  |     EXPECT_EQ(v[0].first, "answer"); | ||||||
|  |     EXPECT_EQ(v[0].second, 42); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   { | ||||||
|  |     absl::InlinedVector<std::string, 2> v(100); | ||||||
|  |     v.resize(0); | ||||||
|  |     v.shrink_to_fit(); | ||||||
|  |     EXPECT_EQ(v.capacity(), 2);  // inlined capacity
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   { | ||||||
|  |     absl::InlinedVector<std::string, 2> v(100); | ||||||
|  |     v.resize(1); | ||||||
|  |     v.shrink_to_fit(); | ||||||
|  |     EXPECT_EQ(v.capacity(), 2);  // inlined capacity
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   { | ||||||
|  |     absl::InlinedVector<std::string, 2> v(100); | ||||||
|  |     v.resize(2); | ||||||
|  |     v.shrink_to_fit(); | ||||||
|  |     EXPECT_EQ(v.capacity(), 2); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   { | ||||||
|  |     absl::InlinedVector<std::string, 2> v(100); | ||||||
|  |     v.resize(3); | ||||||
|  |     v.shrink_to_fit(); | ||||||
|  |     EXPECT_EQ(v.capacity(), 3); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| TEST(IntVec, Insert) { | TEST(IntVec, Insert) { | ||||||
|   for (int len = 0; len < 20; len++) { |   for (int len = 0; len < 20; len++) { | ||||||
|     for (int pos = 0; pos <= len; pos++) { |     for (int pos = 0; pos <= len; pos++) { | ||||||
|  | @ -1589,6 +1652,20 @@ TEST(AllocatorSupportTest, CountAllocations) { | ||||||
|     AllocVec v3(std::move(v), alloc3); |     AllocVec v3(std::move(v), alloc3); | ||||||
|     EXPECT_THAT(allocated3, v3.size() * sizeof(int)); |     EXPECT_THAT(allocated3, v3.size() * sizeof(int)); | ||||||
|   } |   } | ||||||
|  |   EXPECT_EQ(allocated, 0); | ||||||
|  |   { | ||||||
|  |     // Test shrink_to_fit deallocations.
 | ||||||
|  |     AllocVec v(8, 2, alloc); | ||||||
|  |     EXPECT_EQ(allocated, 8 * sizeof(int)); | ||||||
|  |     v.resize(5); | ||||||
|  |     EXPECT_EQ(allocated, 8 * sizeof(int)); | ||||||
|  |     v.shrink_to_fit(); | ||||||
|  |     EXPECT_EQ(allocated, 5 * sizeof(int)); | ||||||
|  |     v.resize(4); | ||||||
|  |     EXPECT_EQ(allocated, 5 * sizeof(int)); | ||||||
|  |     v.shrink_to_fit(); | ||||||
|  |     EXPECT_EQ(allocated, 0); | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST(AllocatorSupportTest, SwapBothAllocated) { | TEST(AllocatorSupportTest, SwapBothAllocated) { | ||||||
|  |  | ||||||
|  | @ -460,13 +460,10 @@ inline bool operator>=(uint128 lhs, uint128 rhs) { | ||||||
| // Unary operators.
 | // Unary operators.
 | ||||||
| 
 | 
 | ||||||
| inline uint128 operator-(uint128 val) { | inline uint128 operator-(uint128 val) { | ||||||
|   const uint64_t hi_flip = ~Uint128High64(val); |   uint64_t hi = ~Uint128High64(val); | ||||||
|   const uint64_t lo_flip = ~Uint128Low64(val); |   uint64_t lo = ~Uint128Low64(val) + 1; | ||||||
|   const uint64_t lo_add = lo_flip + 1; |   if (lo == 0) ++hi;  // carry
 | ||||||
|   if (lo_add < lo_flip) { |   return MakeUint128(hi, lo); | ||||||
|     return MakeUint128(hi_flip + 1, lo_add); |  | ||||||
|   } |  | ||||||
|   return MakeUint128(hi_flip, lo_add); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline bool operator!(uint128 val) { | inline bool operator!(uint128 val) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue