inlined_vector.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. *
  3. * Copyright 2017 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #ifndef GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H
  19. #define GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H
  20. #include <cassert>
  21. #include "src/core/lib/gprpp/memory.h"
  22. namespace grpc_core {
  23. // NOTE: We eventually want to use absl::InlinedVector here. However,
  24. // there are currently build problems that prevent us from using absl.
  25. // In the interim, we define a custom implementation as a place-holder,
  26. // with the intent to eventually replace this with the absl
  27. // implementation.
  28. //
  29. // This place-holder implementation does not implement the full set of
  30. // functionality from the absl version; it has just the methods that we
  31. // currently happen to need in gRPC. If additional functionality is
  32. // needed before this gets replaced with the absl version, it can be
  33. // added, with the following proviso:
  34. //
  35. // ANY METHOD ADDED HERE MUST COMPLY WITH THE INTERFACE IN THE absl
  36. // IMPLEMENTATION!
  37. //
  38. // TODO(nnoble, roth): Replace this with absl::InlinedVector once we
  39. // integrate absl into the gRPC build system in a usable way.
  40. template <typename T, size_t N>
  41. class InlinedVector {
  42. public:
  43. InlinedVector() { init_data(); }
  44. ~InlinedVector() { destroy_elements(); }
  45. // For now, we do not support copying.
  46. InlinedVector(const InlinedVector&) = delete;
  47. InlinedVector& operator=(const InlinedVector&) = delete;
  48. T& operator[](size_t offset) {
  49. assert(offset < size_);
  50. if (offset < N) {
  51. return *reinterpret_cast<T*>(inline_ + offset);
  52. } else {
  53. return dynamic_[offset - N];
  54. }
  55. }
  56. const T& operator[](size_t offset) const {
  57. assert(offset < size_);
  58. if (offset < N) {
  59. return *reinterpret_cast<const T*>(inline_ + offset);
  60. } else {
  61. return dynamic_[offset - N];
  62. }
  63. }
  64. template <typename... Args>
  65. void emplace_back(Args&&... args) {
  66. if (size_ < N) {
  67. new (&inline_[size_]) T(std::forward<Args>(args)...);
  68. } else {
  69. if (size_ - N == dynamic_capacity_) {
  70. size_t new_capacity =
  71. dynamic_capacity_ == 0 ? 2 : dynamic_capacity_ * 2;
  72. T* new_dynamic = static_cast<T*>(gpr_malloc(sizeof(T) * new_capacity));
  73. for (size_t i = 0; i < dynamic_capacity_; ++i) {
  74. new (&new_dynamic[i]) T(std::move(dynamic_[i]));
  75. dynamic_[i].~T();
  76. }
  77. gpr_free(dynamic_);
  78. dynamic_ = new_dynamic;
  79. dynamic_capacity_ = new_capacity;
  80. }
  81. new (&dynamic_[size_ - N]) T(std::forward<Args>(args)...);
  82. }
  83. ++size_;
  84. }
  85. void push_back(const T& value) { emplace_back(value); }
  86. void push_back(T&& value) { emplace_back(std::move(value)); }
  87. size_t size() const { return size_; }
  88. void clear() {
  89. destroy_elements();
  90. init_data();
  91. }
  92. private:
  93. void init_data() {
  94. dynamic_ = nullptr;
  95. size_ = 0;
  96. dynamic_capacity_ = 0;
  97. }
  98. void destroy_elements() {
  99. for (size_t i = 0; i < size_ && i < N; ++i) {
  100. T& value = *reinterpret_cast<T*>(inline_ + i);
  101. value.~T();
  102. }
  103. if (size_ > N) { // Avoid subtracting two signed values.
  104. for (size_t i = 0; i < size_ - N; ++i) {
  105. dynamic_[i].~T();
  106. }
  107. }
  108. gpr_free(dynamic_);
  109. }
  110. typename std::aligned_storage<sizeof(T)>::type inline_[N];
  111. T* dynamic_;
  112. size_t size_;
  113. size_t dynamic_capacity_;
  114. };
  115. } // namespace grpc_core
  116. #endif /* GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H */