| 
					
				 | 
			
			
				@@ -24,229 +24,14 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <cassert> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <cstring> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include "src/core/lib/gprpp/memory.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#if GRPC_USE_ABSL 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "absl/container/inlined_vector.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/lib/gprpp/memory.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 namespace grpc_core { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#if GRPC_USE_ABSL 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 template <typename T, size_t N, typename A = std::allocator<T>> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using InlinedVector = absl::InlinedVector<T, N, A>; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// NOTE: We eventually want to use absl::InlinedVector here.  However, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// there are currently build problems that prevent us from using absl. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// In the interim, we define a custom implementation as a place-holder, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// with the intent to eventually replace this with the absl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// implementation. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// This place-holder implementation does not implement the full set of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// functionality from the absl version; it has just the methods that we 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// currently happen to need in gRPC.  If additional functionality is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// needed before this gets replaced with the absl version, it can be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// added, with the following proviso: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// ANY METHOD ADDED HERE MUST COMPLY WITH THE INTERFACE IN THE absl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// IMPLEMENTATION! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// TODO(nnoble, roth): Replace this with absl::InlinedVector once we 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// integrate absl into the gRPC build system in a usable way. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-template <typename T, size_t N> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class InlinedVector { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  InlinedVector() { init_data(); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ~InlinedVector() { destroy_elements(); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // copy constructor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  InlinedVector(const InlinedVector& v) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    init_data(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    copy_from(v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  InlinedVector& operator=(const InlinedVector& v) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (this != &v) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      copy_from(v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return *this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // move constructor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  InlinedVector(InlinedVector&& v) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    init_data(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    move_from(v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  InlinedVector& operator=(InlinedVector&& v) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (this != &v) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      move_from(v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return *this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  T* data() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return dynamic_ != nullptr ? dynamic_ : reinterpret_cast<T*>(inline_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const T* data() const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return dynamic_ != nullptr ? dynamic_ : reinterpret_cast<const T*>(inline_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  T& operator[](size_t offset) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    assert(offset < size_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return data()[offset]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const T& operator[](size_t offset) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    assert(offset < size_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return data()[offset]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool operator==(const InlinedVector& other) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (size_ != other.size_) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (size_t i = 0; i < size_; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // Note that this uses == instead of != so that the data class doesn't 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // have to implement !=. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (!(data()[i] == other.data()[i])) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool operator!=(const InlinedVector& other) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return !(*this == other); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void reserve(size_t capacity) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (capacity > capacity_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      T* new_dynamic = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          std::alignment_of<T>::value == 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              ? static_cast<T*>(gpr_malloc(sizeof(T) * capacity)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              : static_cast<T*>(gpr_malloc_aligned( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    sizeof(T) * capacity, std::alignment_of<T>::value)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      move_elements(data(), new_dynamic, size_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      free_dynamic(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      dynamic_ = new_dynamic; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      capacity_ = capacity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void resize(size_t new_size) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    while (new_size > size_) emplace_back(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    while (new_size < size_) pop_back(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  template <typename... Args> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void emplace_back(Args&&... args) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (size_ == capacity_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      reserve(capacity_ * 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    new (&(data()[size_])) T(std::forward<Args>(args)...); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ++size_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void push_back(const T& value) { emplace_back(value); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void push_back(T&& value) { emplace_back(std::move(value)); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void pop_back() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    assert(!empty()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    size_t s = size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    T& value = data()[s - 1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    value.~T(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    size_--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  T& front() { return data()[0]; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const T& front() const { return data()[0]; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  T& back() { return data()[size_ - 1]; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const T& back() const { return data()[size_ - 1]; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  size_t size() const { return size_; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool empty() const { return size_ == 0; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  size_t capacity() const { return capacity_; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void clear() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    destroy_elements(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    init_data(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void copy_from(const InlinedVector& v) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // if v is allocated, make sure we have enough capacity. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (v.dynamic_ != nullptr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      reserve(v.capacity_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // copy over elements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (size_t i = 0; i < v.size_; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      new (&(data()[i])) T(v[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // copy over metadata 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    size_ = v.size_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    capacity_ = v.capacity_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void move_from(InlinedVector& v) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // if v is allocated, then we steal its dynamic array; otherwise, we 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // move the elements individually. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (v.dynamic_ != nullptr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      dynamic_ = v.dynamic_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      move_elements(v.data(), data(), v.size_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // copy over metadata 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    size_ = v.size_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    capacity_ = v.capacity_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // null out the original 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    v.init_data(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  static void move_elements(T* src, T* dst, size_t num_elements) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (size_t i = 0; i < num_elements; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      new (&dst[i]) T(std::move(src[i])); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      src[i].~T(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void init_data() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    dynamic_ = nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    size_ = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    capacity_ = N; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void destroy_elements() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (size_t i = 0; i < size_; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      T& value = data()[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      value.~T(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    free_dynamic(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void free_dynamic() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (dynamic_ != nullptr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (std::alignment_of<T>::value == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        gpr_free(dynamic_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        gpr_free_aligned(dynamic_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  typename std::aligned_storage<sizeof(T)>::type inline_[N]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  T* dynamic_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  size_t size_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  size_t capacity_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }  // namespace grpc_core 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif /* GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H */ 
			 |