159 using value_type = T;
160 using reference = T&;
161 using const_reference =
const T&;
162 using size_type = size_t;
163 using difference_type = ssize_t;
164 using reference_type = T&;
165 using const_reference_type =
const T&;
167 using const_pointer =
const T*;
168 using iterator = std::conditional_t<
169 Traits::kIteratorPreferSpeed,
170 cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T,
false>,
171 cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T,
false>>;
172 using const_iterator = std::conditional_t<
173 Traits::kIteratorPreferSpeed,
174 cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T,
true>,
175 cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T,
true>>;
176 using reverse_iterator = std::reverse_iterator<iterator>;
177 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
190 : firstBucketShift_(detail::log2(
191 detail::nextPow2(std::max(startCapacity, SizeTraits::kDefaultCapacity / 2)))),
192 firstBucketLen_(size_type{1} << firstBucketShift_) {
193 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
194 buffers_[0].store(firstTwo, std::memory_order_release);
195 buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_release);
202 size_.store(startSize, std::memory_order_relaxed);
203 T* buf = buffers_[0].load(std::memory_order_relaxed);
204 for (
size_t i = 0; i < startSize; ++i) {
214 size_.store(startSize, std::memory_order_relaxed);
215 T* buf = buffers_[0].load(std::memory_order_relaxed);
216 for (
size_t i = 0; i < startSize; ++i) {
217 new (buf + i) T(defaultValue);
224 template <
typename InIterator>
233 template <
typename InIterator>
236 size_.store(startSize, std::memory_order_relaxed);
237 assert(std::distance(start,
end) ==
static_cast<difference_type
>(startSize));
257 : buffers_(std::move(other.buffers_)),
258 firstBucketShift_(other.firstBucketShift_),
259 firstBucketLen_(other.firstBucketLen_),
260 size_(other.size_.load(std::memory_order_relaxed)) {
261 other.size_.store(0, std::memory_order_relaxed);
264 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
265 other.buffers_[0].store(firstTwo, std::memory_order_relaxed);
266 other.buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_relaxed);
273 if (&other ==
this) {
279 size_.store(other.
size(), std::memory_order_relaxed);
290 if (&other ==
this) {
295 swap(firstBucketShift_, other.firstBucketShift_);
296 swap(firstBucketLen_, other.firstBucketLen_);
297 buffers_ = std::move(other.buffers_);
298 size_t curLen = size_.load(std::memory_order_relaxed);
299 size_.store(other.size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
300 other.size_.store(curLen, std::memory_order_relaxed);
311 void assign(size_type count,
const T& value) {
314 size_.store(count, std::memory_order_relaxed);
315 internalFillN(
begin(), count, value);
326 typename =
typename std::iterator_traits<It>::difference_type,
327 typename =
typename std::iterator_traits<It>::pointer,
328 typename =
typename std::iterator_traits<It>::reference,
329 typename =
typename std::iterator_traits<It>::value_type,
330 typename =
typename std::iterator_traits<It>::iterator_category>
333 auto count = std::distance(start,
end);
335 size_.store(count, std::memory_order_relaxed);
345 buffers_.allocAsNecessary({0, 0, firstBucketLen_},
capacity, bucketAndSubIndex(
capacity));
354 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
357 }
else if (curLen > len) {
359 auto newEnd =
begin() + len;
363 }
while (it != newEnd);
364 size_.store(len, std::memory_order_relaxed);
374 void resize(difference_type len,
const T& value) {
375 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
378 }
else if (curLen > len) {
380 auto newEnd =
begin() + len;
384 }
while (it != newEnd);
385 size_.store(len, std::memory_order_relaxed);
394 return 2 * firstBucketLen_;
402 size_t cap = 2 * firstBucketLen_;
403 for (
size_t b = 2; b < kMaxBuffers; ++b) {
404 if (!buffers_[b].load(std::memory_order_relaxed)) {
417 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
418 size_t len = binfo.bucketIndex;
419 size_t cap = binfo.bucketCapacity;
420 size_t b = binfo.bucket;
422 T* buf = buffers_[b].load(std::memory_order_relaxed);
432 size_.store(0, std::memory_order_release);
440 constexpr size_t kMaxExtra = 2;
441 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
444 size_t startBucket = std::max<size_t>(2, binfo.bucket + kMaxExtra);
446 for (
size_t b = startBucket; b < kMaxBuffers; ++b) {
447 T* ptr = buffers_[b].load(std::memory_order_relaxed);
451 if (buffers_.shouldDealloc(b)) {
454 buffers_[b].store(
nullptr, std::memory_order_release);
464 cv::dealloc<T>(buffers_[0].load(std::memory_order_acquire));
473 iterator
insert(const_iterator pos,
const T& value) {
474 auto it = insertPartial(pos);
485 iterator
insert(const_iterator pos, T&& value) {
486 auto it = insertPartial(pos);
487 new (&*it) T(std::move(value));
498 iterator
insert(const_iterator pos, size_type count,
const T& value) {
499 auto it = insertPartial(pos, count);
500 std::fill_n(it, count, value);
513 typename =
typename std::iterator_traits<InputIt>::difference_type,
514 typename =
typename std::iterator_traits<InputIt>::pointer,
515 typename =
typename std::iterator_traits<InputIt>::reference,
516 typename =
typename std::iterator_traits<InputIt>::value_type,
517 typename =
typename std::iterator_traits<InputIt>::iterator_category>
518 iterator
insert(const_iterator pos, InputIt first, InputIt last) {
519 size_t len = std::distance(first, last);
520 auto it = insertPartial(pos, len);
521 std::copy_n(first, len, it);
531 iterator
insert(const_iterator pos, std::initializer_list<T> ilist) {
532 return insert(pos, ilist.begin(), ilist.end());
541 iterator
erase(const_iterator pos) {
546 size_.fetch_sub(1, std::memory_order_relaxed);
555 return std::move(pos + 1, const_iterator(e), it);
566 iterator
erase(const_iterator first, const_iterator last) {
567 size_t len = std::distance(first, last);
569 size_t startIdx = first - it;
571 return it + (startIdx + len);
575 auto e_it = std::move(last,
cend(), it);
582 }
while (e_it != last);
584 size_.fetch_sub(len, std::memory_order_relaxed);
611 template <
typename... Args>
613 auto index = size_.fetch_add(1, std::memory_order_relaxed);
614 auto binfo = bucketAndSubIndex(index);
616 buffers_.allocAsNecessary(binfo);
618 iterator ret{
this, index, binfo};
620 if (Traits::kIteratorPreferSpeed) {
621 new (&*ret) T(std::forward<Args>(args)...);
623 new (buffers_[binfo.bucket] + binfo.bucketIndex) T(std::forward<Args>(args)...);
636 template <
typename Gen>
638 iterator ret = growByUninitialized(delta);
639 for (
auto it = ret; delta--; ++it) {
651 iterator
grow_by(size_type delta,
const T& t) {
652 iterator ret = growByUninitialized(delta);
653 internalFillN(ret, delta, t);
663 iterator ret = growByUninitialized(delta);
664 internalFillDefaultN(ret, delta);
676 typename =
typename std::iterator_traits<It>::difference_type,
677 typename =
typename std::iterator_traits<It>::pointer,
678 typename =
typename std::iterator_traits<It>::reference,
679 typename =
typename std::iterator_traits<It>::value_type,
680 typename =
typename std::iterator_traits<It>::iterator_category>
682 iterator ret = growByUninitialized(std::distance(start,
end));
683 internalInit(start,
end, ret);
692 iterator
grow_by(std::initializer_list<T> initList) {
693 return grow_by(std::begin(initList), std::end(initList));
703 size_t curSize = size_.load(std::memory_order_relaxed);
707 return {
this, n - 1, bucketAndSubIndex(n - 1)};
718 size_t curSize = size_.load(std::memory_order_relaxed);
720 return grow_by(n - curSize, t);
722 return {
this, n - 1, bucketAndSubIndex(n - 1)};
729 auto binfo = bucketAndSubIndex(size_.fetch_sub(1, std::memory_order_relaxed) - 1);
730 T* elt = buffers_[binfo.bucket].load(std::memory_order_relaxed) + binfo.bucketIndex;
743 auto binfo = bucketAndSubIndexForIndex(index);
744 T* buf = buffers_[binfo.bucket].load(std::memory_order_relaxed);
745 return buf[binfo.bucketIndex];
757 auto binfo = bucketAndSubIndexForIndex(index);
758 T* buf = buffers_[binfo.bucket].load(std::memory_order_relaxed);
759 return buf[binfo.bucketIndex];
771 const T&
at(size_type index)
const {
772#if defined(__cpp_exceptions)
773 if (index >= size_.load(std::memory_order_relaxed)) {
774 throw std::out_of_range(
"Index too large");
789 T&
at(size_type index) {
790#if defined(__cpp_exceptions)
791 if (index >= size_.load(std::memory_order_relaxed)) {
792 throw std::out_of_range(
"Index too large");
806 return {
this, 0, {0, 0, firstBucketLen_}};
818 size_t curSize = size_.load(std::memory_order_relaxed);
819 auto binfo = bucketAndSubIndex(curSize);
820 return {
this, curSize, binfo};
831 return {
this, 0, {0, 0, firstBucketLen_}};
842 const_iterator
end()
const {
843 size_t curSize = size_.load(std::memory_order_relaxed);
844 auto binfo = bucketAndSubIndex(curSize);
845 return {
this, curSize, binfo};
856 return {
this, 0, {0, 0, firstBucketLen_}};
868 size_t curSize = size_.load(std::memory_order_relaxed);
869 auto binfo = bucketAndSubIndex(curSize);
870 return {
this, curSize, binfo};
882 return reverse_iterator(
end());
893 return reverse_iterator(
begin());
905 return const_reverse_iterator(
cend());
915 const_reverse_iterator
rend()
const {
916 return const_reverse_iterator(
cbegin());
925 return size_.load(std::memory_order_relaxed) == 0;
934 return Traits::kMaxVectorSize;
943 return size_.load(std::memory_order_relaxed);
951 return *buffers_[0].load(std::memory_order_relaxed);
959 return *buffers_[0].load(std::memory_order_relaxed);
986 swap(firstBucketShift_, oth.firstBucketShift_);
987 swap(firstBucketLen_, oth.firstBucketLen_);
988 size_t othlen = oth.size_.load(std::memory_order_relaxed);
989 oth.size_.store(size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
990 size_.store(othlen, std::memory_order_relaxed);
993 buffers_ = std::move(oth.buffers_);
997 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndexForIndex(
size_t index)
const {
998#if defined(__clang__)
999 if (index < firstBucketLen_) {
1000 return {0, index, firstBucketLen_};
1003 size_t l2idx = detail::log2(index);
1004 size_t bucket = (l2idx + 1) - firstBucketShift_;
1005 size_t bucketCapacity =
size_t{1} << l2idx;
1006 size_t bucketIndex = index - bucketCapacity;
1008 return {bucket, bucketIndex, bucketCapacity};
1010 return bucketAndSubIndex(index);
1014 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndex(
size_t index)
const {
1015 size_t l2idx = detail::log2(index | 1);
1016 size_t bucket = (l2idx + 1) - firstBucketShift_;
1017 size_t bucketCapacity =
size_t{1} << l2idx;
1018 size_t bucketIndex = index - bucketCapacity;
1020 bucket = index < firstBucketLen_ ? 0 : bucket;
1021 bucketIndex = index < firstBucketLen_ ? index : bucketIndex;
1022 bucketCapacity = index < firstBucketLen_ ? firstBucketLen_ : bucketCapacity;
1024 return {bucket, bucketIndex, bucketCapacity};
1027 template <
typename InIterator>
1028 void internalInit(InIterator start, InIterator
end, iterator it) {
1029 while (start !=
end) {
1030 new (&*it) T(*start);
1036 void internalFillN(iterator it,
size_t len,
const T& value) {
1037 for (; len--; ++it) {
1038 new (&*it) T(value);
1042 void internalFillDefaultN(iterator it,
size_t len) {
1043 for (; len--; ++it) {
1048 iterator growByUninitialized(size_type delta) {
1049 auto index = size_.fetch_add(delta, std::memory_order_relaxed);
1050 auto binfo = bucketAndSubIndex(index);
1051 buffers_.allocAsNecessary(binfo, delta, bucketAndSubIndex(index + delta));
1052 return {
this, index, binfo};
1055 iterator insertPartial(const_iterator pos) {
1057 auto index = size_.fetch_add(1, std::memory_order_relaxed);
1058 auto binfo = bucketAndSubIndex(index);
1059 buffers_.allocAsNecessary(binfo);
1061 return std::move_backward(pos, const_iterator(e), e + 1) - 1;
1064 iterator insertPartial(const_iterator pos,
size_t len) {
1066 auto index = size_.fetch_add(len, std::memory_order_relaxed);
1067 buffers_.allocAsNecessary(bucketAndSubIndex(index), len, bucketAndSubIndex(index + len));
1068 for (
auto it = e + len; it != e;) {
1072 return std::move_backward(pos, const_iterator(e), e + len) - len;
1075 alignas(kCacheLineSize) cv::ConVecBuffer<
1077 SizeTraits::kDefaultCapacity / 2,
1078 SizeTraits::kMaxVectorSize,
1079 Traits::kPreferBuffersInline,
1080 Traits::kReallocStrategy> buffers_;
1081 static constexpr size_t kMaxBuffers =
decltype(buffers_)::kMaxBuffers;
1083 size_t firstBucketShift_;
1084 size_t firstBucketLen_;
1086 alignas(kCacheLineSize) std::atomic<size_t> size_{0};
1089 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, false>;
1090 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, true>;