1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
9 #include <initializer_list>
17 template <class T
, size_t kSize
= 8>
18 class autovector
: public std::vector
<T
> {
19 using std::vector
<T
>::vector
;
22 // A vector that leverages pre-allocated stack-based array to achieve better
23 // performance for array with small amount of items.
25 // The interface resembles that of vector, but with less features since we aim
26 // to solve the problem that we have in hand, rather than implementing a
27 // full-fledged generic container.
29 // Currently we don't support:
30 // * reserve()/shrink_to_fit()
31 // If used correctly, in most cases, people should not touch the
32 // underlying vector at all.
33 // * random insert()/erase(), please only use push_back()/pop_back().
34 // * No move/swap operations. Each autovector instance has a
35 // stack-allocated array and if we want support move/swap operations, we
36 // need to copy the arrays other than just swapping the pointers. In this
37 // case we'll just explicitly forbid these operations since they may
38 // lead users to make false assumption by thinking they are inexpensive
41 // Naming style of public methods almost follows that of the STL's.
42 template <class T
, size_t kSize
= 8>
45 // General STL-style container member types.
47 typedef typename
std::vector
<T
>::difference_type difference_type
;
48 typedef typename
std::vector
<T
>::size_type size_type
;
49 typedef value_type
& reference
;
50 typedef const value_type
& const_reference
;
51 typedef value_type
* pointer
;
52 typedef const value_type
* const_pointer
;
54 // This class is the base for regular/const iterator
55 template <class TAutoVector
, class TValueType
>
59 typedef iterator_impl
<TAutoVector
, TValueType
> self_type
;
60 typedef TValueType value_type
;
61 typedef TValueType
& reference
;
62 typedef TValueType
* pointer
;
63 typedef typename
TAutoVector::difference_type difference_type
;
64 typedef std::random_access_iterator_tag iterator_category
;
66 iterator_impl(TAutoVector
* vect
, size_t index
)
67 : vect_(vect
), index_(index
) {};
68 iterator_impl(const iterator_impl
&) = default;
70 iterator_impl
& operator=(const iterator_impl
&) = default;
74 self_type
& operator++() {
80 self_type
operator++(int) {
87 self_type
& operator--() {
93 self_type
operator--(int) {
99 self_type
operator-(difference_type len
) const {
100 return self_type(vect_
, index_
- len
);
103 difference_type
operator-(const self_type
& other
) const {
104 assert(vect_
== other
.vect_
);
105 return index_
- other
.index_
;
108 self_type
operator+(difference_type len
) const {
109 return self_type(vect_
, index_
+ len
);
112 self_type
& operator+=(difference_type len
) {
117 self_type
& operator-=(difference_type len
) {
123 reference
operator*() {
124 assert(vect_
->size() >= index_
);
125 return (*vect_
)[index_
];
128 const_reference
operator*() const {
129 assert(vect_
->size() >= index_
);
130 return (*vect_
)[index_
];
133 pointer
operator->() {
134 assert(vect_
->size() >= index_
);
135 return &(*vect_
)[index_
];
138 const_pointer
operator->() const {
139 assert(vect_
->size() >= index_
);
140 return &(*vect_
)[index_
];
144 // -- Logical Operators
145 bool operator==(const self_type
& other
) const {
146 assert(vect_
== other
.vect_
);
147 return index_
== other
.index_
;
150 bool operator!=(const self_type
& other
) const { return !(*this == other
); }
152 bool operator>(const self_type
& other
) const {
153 assert(vect_
== other
.vect_
);
154 return index_
> other
.index_
;
157 bool operator<(const self_type
& other
) const {
158 assert(vect_
== other
.vect_
);
159 return index_
< other
.index_
;
162 bool operator>=(const self_type
& other
) const {
163 assert(vect_
== other
.vect_
);
164 return index_
>= other
.index_
;
167 bool operator<=(const self_type
& other
) const {
168 assert(vect_
== other
.vect_
);
169 return index_
<= other
.index_
;
173 TAutoVector
* vect_
= nullptr;
177 typedef iterator_impl
<autovector
, value_type
> iterator
;
178 typedef iterator_impl
<const autovector
, const value_type
> const_iterator
;
179 typedef std::reverse_iterator
<iterator
> reverse_iterator
;
180 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
182 autovector() : values_(reinterpret_cast<pointer
>(buf_
)) {}
184 autovector(std::initializer_list
<T
> init_list
)
185 : values_(reinterpret_cast<pointer
>(buf_
)) {
186 for (const T
& item
: init_list
) {
191 ~autovector() { clear(); }
193 // -- Immutable operations
194 // Indicate if all data resides in in-stack data structure.
195 bool only_in_stack() const {
196 // If no element was inserted at all, the vector's capacity will be `0`.
197 return vect_
.capacity() == 0;
200 size_type
size() const { return num_stack_items_
+ vect_
.size(); }
202 // resize does not guarantee anything about the contents of the newly
203 // available elements
204 void resize(size_type n
) {
206 vect_
.resize(n
- kSize
);
207 while (num_stack_items_
< kSize
) {
208 new ((void*)(&values_
[num_stack_items_
++])) value_type();
210 num_stack_items_
= kSize
;
213 while (num_stack_items_
< n
) {
214 new ((void*)(&values_
[num_stack_items_
++])) value_type();
216 while (num_stack_items_
> n
) {
217 values_
[--num_stack_items_
].~value_type();
222 bool empty() const { return size() == 0; }
224 const_reference
operator[](size_type n
) const {
229 return vect_
[n
- kSize
];
232 reference
operator[](size_type n
) {
237 return vect_
[n
- kSize
];
240 const_reference
at(size_type n
) const {
245 reference
at(size_type n
) {
255 const_reference
front() const {
265 const_reference
back() const {
270 // -- Mutable Operations
271 void push_back(T
&& item
) {
272 if (num_stack_items_
< kSize
) {
273 new ((void*)(&values_
[num_stack_items_
])) value_type();
274 values_
[num_stack_items_
++] = std::move(item
);
276 vect_
.push_back(item
);
280 void push_back(const T
& item
) {
281 if (num_stack_items_
< kSize
) {
282 new ((void*)(&values_
[num_stack_items_
])) value_type();
283 values_
[num_stack_items_
++] = item
;
285 vect_
.push_back(item
);
289 template <class... Args
>
290 void emplace_back(Args
&&... args
) {
291 if (num_stack_items_
< kSize
) {
292 new ((void*)(&values_
[num_stack_items_
++]))
293 value_type(std::forward
<Args
>(args
)...);
295 vect_
.emplace_back(std::forward
<Args
>(args
)...);
301 if (!vect_
.empty()) {
304 values_
[--num_stack_items_
].~value_type();
309 while (num_stack_items_
> 0) {
310 values_
[--num_stack_items_
].~value_type();
315 // -- Copy and Assignment
316 autovector
& assign(const autovector
& other
);
318 autovector(const autovector
& other
) { assign(other
); }
320 autovector
& operator=(const autovector
& other
) { return assign(other
); }
322 // -- Iterator Operations
323 iterator
begin() { return iterator(this, 0); }
325 const_iterator
begin() const { return const_iterator(this, 0); }
327 iterator
end() { return iterator(this, this->size()); }
329 const_iterator
end() const { return const_iterator(this, this->size()); }
331 reverse_iterator
rbegin() { return reverse_iterator(end()); }
333 const_reverse_iterator
rbegin() const {
334 return const_reverse_iterator(end());
337 reverse_iterator
rend() { return reverse_iterator(begin()); }
339 const_reverse_iterator
rend() const {
340 return const_reverse_iterator(begin());
344 size_type num_stack_items_
= 0; // current number of items
346 value_type
)) char buf_
[kSize
*
347 sizeof(value_type
)]; // the first `kSize` items
349 // used only if there are more than `kSize` items.
350 std::vector
<T
> vect_
;
353 template <class T
, size_t kSize
>
354 autovector
<T
, kSize
>& autovector
<T
, kSize
>::assign(const autovector
& other
) {
355 values_
= reinterpret_cast<pointer
>(buf_
);
356 // copy the internal vector
357 vect_
.assign(other
.vect_
.begin(), other
.vect_
.end());
360 num_stack_items_
= other
.num_stack_items_
;
361 std::copy(other
.values_
, other
.values_
+ num_stack_items_
, values_
);
365 #endif // ROCKSDB_LITE
366 } // namespace rocksdb