quill
InlinedVector.h
1 
7 #pragma once
8 
9 #include <cstddef>
10 #include <cstdint>
11 #include <cstring>
12 #include <type_traits>
13 
14 #include "quill/core/Attributes.h"
15 #include "quill/core/Common.h"
16 #include "quill/core/QuillError.h"
17 
18 #if defined(__GNUC__) && !defined(__clang__)
19  #pragma GCC diagnostic push
20  #pragma GCC diagnostic ignored "-Warray-bounds"
21  #pragma GCC diagnostic ignored "-Wstringop-overflow"
22 #elif defined(__clang__)
23  #pragma GCC diagnostic push
24  #pragma GCC diagnostic ignored "-Warray-bounds"
25 #elif defined(_WIN32) && defined(_MSC_VER)
26  #pragma warning(push)
27  #pragma warning(disable : 4789)
28 #endif
29 
30 QUILL_BEGIN_NAMESPACE
31 
32 namespace detail
33 {
34 
35 template <typename T, size_t N>
37 {
38 public:
39  using value_type = T;
40  static_assert(std::is_trivially_copyable_v<value_type>, "value_type must be trivially copyable");
41 
42  InlinedVector() noexcept
43  {
44  for (size_t i = 0; i < _capacity; ++i)
45  {
46  _storage.inline_buffer[i] = value_type{};
47  }
48  }
49 
50  ~InlinedVector()
51  {
52  if (_capacity != N)
53  {
54  delete[] _storage.heap_buffer;
55  }
56  }
57 
61  InlinedVector(InlinedVector const& other) = delete;
62  InlinedVector& operator=(InlinedVector const& other) = delete;
63 
67  QUILL_ATTRIBUTE_HOT value_type push_back(value_type value)
68  {
69  if (_size == _capacity)
70  {
71  size_t const new_capacity = _capacity * 2;
72  auto* new_data = new value_type[new_capacity];
73 
74  if (QUILL_UNLIKELY(new_capacity <= _capacity))
75  {
76  QUILL_THROW(
77  QuillError{"This unreachable code is here only to suppress gcc false positive warnings"});
78  }
79 
80  if (_capacity == N)
81  {
82  // Entering here for the first time, then we copy the inline storage
83  // Use memcpy for trivially copyable types to avoid false positive warnings with LTO
84  std::memcpy(new_data, _storage.inline_buffer, _size * sizeof(value_type));
85  }
86  else
87  {
88  // Use memcpy for trivially copyable types to avoid false positive warnings with LTO
89  std::memcpy(new_data, _storage.heap_buffer, _size * sizeof(value_type));
90  delete[] _storage.heap_buffer;
91  }
92 
93  _storage.heap_buffer = new_data;
94  _capacity = new_capacity;
95  }
96 
97  if (_capacity == N)
98  {
99  _storage.inline_buffer[_size] = value;
100  }
101  else
102  {
103  _storage.heap_buffer[_size] = value;
104  }
105 
106  ++_size;
107 
108  return value;
109  }
110 
114  QUILL_ATTRIBUTE_HOT value_type operator[](size_t index) const
115  {
116  if (QUILL_UNLIKELY(index >= _size))
117  {
118  QUILL_THROW(QuillError{"index out of bounds"});
119  }
120 
121  if (_capacity == N)
122  {
123  return _storage.inline_buffer[index];
124  }
125  else
126  {
127  return _storage.heap_buffer[index];
128  }
129  }
130 
134  QUILL_ATTRIBUTE_HOT void assign(size_t index, value_type value)
135  {
136  if (QUILL_UNLIKELY(index >= _size))
137  {
138  QUILL_THROW(QuillError{"index out of bounds"});
139  }
140 
141  if (_capacity == N)
142  {
143  _storage.inline_buffer[index] = value;
144  }
145  else
146  {
147  _storage.heap_buffer[index] = value;
148  }
149  }
150 
151  QUILL_NODISCARD QUILL_ATTRIBUTE_HOT size_t size() const noexcept { return _size; }
152  QUILL_NODISCARD size_t capacity() const noexcept { return _capacity; }
153  QUILL_ATTRIBUTE_HOT void clear() noexcept { _size = 0; }
154 
155 private:
156  union Storage
157  {
158  value_type inline_buffer[N];
159  value_type* heap_buffer;
160  } _storage;
161 
162  size_t _size{0};
163  size_t _capacity{N};
164 };
165 
171 static_assert(sizeof(SizeCacheVector) <= QUILL_CACHE_LINE_SIZE,
172  "SizeCacheVector should not exceed a cache line");
173 } // namespace detail
174 
175 QUILL_END_NAMESPACE
176 
177 #if defined(__GNUC__) && !defined(__clang__)
178  #pragma GCC diagnostic pop
179 #elif defined(__clang__)
180  #pragma GCC diagnostic pop
181 #elif defined(_WIN32) && defined(_MSC_VER)
182  #pragma warning(pop)
183 #endif
QUILL_ATTRIBUTE_HOT value_type push_back(value_type value)
Push back a new element.
Definition: InlinedVector.h:67
QUILL_ATTRIBUTE_HOT value_type operator[](size_t index) const
Access element.
Definition: InlinedVector.h:114
QUILL_ATTRIBUTE_HOT void assign(size_t index, value_type value)
Assign value at index.
Definition: InlinedVector.h:134
Definition: InlinedVector.h:36
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:24
Definition: base.h:2198
custom exception
Definition: QuillError.h:45