177 using value_type = T;
178 using reference = T&;
179 using const_reference =
const T&;
180 using size_type = size_t;
181 using difference_type = ssize_t;
182 using reference_type = T&;
183 using const_reference_type =
const T&;
185 using const_pointer =
const T*;
186 using iterator = std::conditional_t<
187 Traits::kIteratorPreferSpeed,
188 cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T,
false>,
189 cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T,
false>>;
190 using const_iterator = std::conditional_t<
191 Traits::kIteratorPreferSpeed,
192 cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T,
true>,
193 cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T,
true>>;
194 using reverse_iterator = std::reverse_iterator<iterator>;
195 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
210 detail::
nextPow2(std::max(startCapacity, SizeTraits::kDefaultCapacity / 2)))),
211 firstBucketLen_(size_type{1} << firstBucketShift_) {
212 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
214 setCachedPtr(0, firstTwo);
215 setCachedPtr(1, firstTwo + firstBucketLen_);
216 buffers_[0].store(firstTwo, std::memory_order_release);
217 buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_release);
224 size_.store(startSize, std::memory_order_relaxed);
225 T* buf = buffers_[0].load(std::memory_order_relaxed);
226 for (
size_t i = 0; i < startSize; ++i) {
236 size_.store(startSize, std::memory_order_relaxed);
237 T* buf = buffers_[0].load(std::memory_order_relaxed);
238 for (
size_t i = 0; i < startSize; ++i) {
239 new (buf + i) T(defaultValue);
246 template <
typename InIterator>
255 template <
typename InIterator>
258 size_.store(startSize, std::memory_order_relaxed);
259 assert(std::distance(start,
end) ==
static_cast<difference_type
>(startSize));
279 : buffers_(std::move(other.buffers_)),
280 firstBucketShift_(other.firstBucketShift_),
281 firstBucketLen_(other.firstBucketLen_),
282 size_(other.size_.load(std::memory_order_relaxed)) {
283 moveCachedPtrsFrom(other);
284 other.size_.store(0, std::memory_order_relaxed);
287 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
288 other.setCachedPtr(0, firstTwo);
289 other.setCachedPtr(1, firstTwo + firstBucketLen_);
290 other.buffers_[0].store(firstTwo, std::memory_order_relaxed);
291 other.buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_relaxed);
298 if (&other ==
this) {
304 size_.store(other.
size(), std::memory_order_relaxed);
315 if (&other ==
this) {
320 swap(firstBucketShift_, other.firstBucketShift_);
321 swap(firstBucketLen_, other.firstBucketLen_);
322 buffers_ = std::move(other.buffers_);
323 swapCachedPtrs(other);
324 size_t curLen = size_.load(std::memory_order_relaxed);
325 size_.store(other.size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
326 other.size_.store(curLen, std::memory_order_relaxed);
337 void assign(size_type count,
const T& value) {
340 size_.store(count, std::memory_order_relaxed);
341 internalFillN(
begin(), count, value);
352 typename =
typename std::iterator_traits<It>::difference_type,
353 typename =
typename std::iterator_traits<It>::pointer,
354 typename =
typename std::iterator_traits<It>::reference,
355 typename =
typename std::iterator_traits<It>::value_type,
356 typename =
typename std::iterator_traits<It>::iterator_category>
359 auto count = std::distance(start,
end);
361 size_.store(count, std::memory_order_relaxed);
371 auto bend = bucketAndSubIndex(
capacity);
372 allocateBufferRange({0, 0, firstBucketLen_},
capacity, bend);
381 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
384 }
else if (curLen > len) {
386 auto newEnd =
begin() + len;
390 }
while (it != newEnd);
391 size_.store(len, std::memory_order_relaxed);
401 void resize(difference_type len,
const T& value) {
402 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
405 }
else if (curLen > len) {
407 auto newEnd =
begin() + len;
411 }
while (it != newEnd);
412 size_.store(len, std::memory_order_relaxed);
421 return 2 * firstBucketLen_;
429 size_t cap = 2 * firstBucketLen_;
430 for (
size_t b = 2; b < kMaxBuffers; ++b) {
431 if (!buffers_[b].load(std::memory_order_relaxed)) {
444 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
445 size_t len = binfo.bucketIndex;
446 size_t cap = binfo.bucketCapacity;
447 size_t b = binfo.bucket;
449 T* buf = buffers_[b].load(std::memory_order_relaxed);
459 size_.store(0, std::memory_order_release);
467 constexpr size_t kMaxExtra = 2;
468 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
471 size_t startBucket = std::max<size_t>(2, binfo.bucket + kMaxExtra);
473 for (
size_t b = startBucket; b < kMaxBuffers; ++b) {
474 T* ptr = buffers_[b].load(std::memory_order_relaxed);
478 if (buffers_.shouldDealloc(b)) {
482 buffers_[b].store(
nullptr, std::memory_order_release);
492 cv::dealloc<T>(buffers_[0].load(std::memory_order_acquire));
501 iterator
insert(const_iterator pos,
const T& value) {
502 auto it = insertPartial(pos);
513 iterator
insert(const_iterator pos, T&& value) {
514 auto it = insertPartial(pos);
515 new (&*it) T(std::move(value));
526 iterator
insert(const_iterator pos, size_type count,
const T& value) {
527 auto it = insertPartial(pos, count);
528 std::fill_n(it, count, value);
541 typename =
typename std::iterator_traits<InputIt>::difference_type,
542 typename =
typename std::iterator_traits<InputIt>::pointer,
543 typename =
typename std::iterator_traits<InputIt>::reference,
544 typename =
typename std::iterator_traits<InputIt>::value_type,
545 typename =
typename std::iterator_traits<InputIt>::iterator_category>
546 iterator
insert(const_iterator pos, InputIt first, InputIt last) {
547 size_t len = std::distance(first, last);
548 auto it = insertPartial(pos, len);
549 std::copy_n(first, len, it);
559 iterator
insert(const_iterator pos, std::initializer_list<T> ilist) {
560 return insert(pos, ilist.begin(), ilist.end());
569 iterator
erase(const_iterator pos) {
574 size_.fetch_sub(1, std::memory_order_relaxed);
583 return std::move(pos + 1, const_iterator(e), it);
594 iterator
erase(const_iterator first, const_iterator last) {
595 size_t len = std::distance(first, last);
597 size_t startIdx = first - it;
599 return it + (startIdx + len);
603 auto e_it = std::move(last,
cend(), it);
610 }
while (e_it != last);
612 size_.fetch_sub(len, std::memory_order_relaxed);
639 template <
typename... Args>
641 auto index = size_.fetch_add(1, std::memory_order_relaxed);
642 auto binfo = bucketAndSubIndex(index);
644 allocateBuffer(binfo);
646 iterator ret{
this, index, binfo};
648 if (Traits::kIteratorPreferSpeed) {
649 new (&*ret) T(std::forward<Args>(args)...);
651 new (buffers_[binfo.bucket] + binfo.bucketIndex) T(std::forward<Args>(args)...);
664 template <
typename Gen>
666 iterator ret = growByUninitialized(delta);
667 for (
auto it = ret; delta--; ++it) {
679 iterator
grow_by(size_type delta,
const T& t) {
680 iterator ret = growByUninitialized(delta);
681 internalFillN(ret, delta, t);
691 iterator ret = growByUninitialized(delta);
692 internalFillDefaultN(ret, delta);
704 typename =
typename std::iterator_traits<It>::difference_type,
705 typename =
typename std::iterator_traits<It>::pointer,
706 typename =
typename std::iterator_traits<It>::reference,
707 typename =
typename std::iterator_traits<It>::value_type,
708 typename =
typename std::iterator_traits<It>::iterator_category>
710 iterator ret = growByUninitialized(std::distance(start,
end));
711 internalInit(start,
end, ret);
720 iterator
grow_by(std::initializer_list<T> initList) {
721 return grow_by(std::begin(initList), std::end(initList));
731 size_t curSize = size_.load(std::memory_order_relaxed);
735 return {
this, n - 1, bucketAndSubIndex(n - 1)};
746 size_t curSize = size_.load(std::memory_order_relaxed);
748 return grow_by(n - curSize, t);
750 return {
this, n - 1, bucketAndSubIndex(n - 1)};
757 auto binfo = bucketAndSubIndex(size_.fetch_sub(1, std::memory_order_relaxed) - 1);
758 T* elt = buffers_[binfo.bucket].load(std::memory_order_relaxed) + binfo.bucketIndex;
770 const T& operator[](size_type index)
const {
771 auto binfo = bucketAndSubIndexForIndex(index);
772 T* buf = cachedBuffer(binfo.bucket);
773 return buf[binfo.bucketIndex];
784 T& operator[](size_type index) {
785 auto binfo = bucketAndSubIndexForIndex(index);
786 T* buf = cachedBuffer(binfo.bucket);
787 return buf[binfo.bucketIndex];
799 const T&
at(size_type index)
const {
800#if defined(__cpp_exceptions)
801 if (index >= size_.load(std::memory_order_relaxed)) {
802 throw std::out_of_range(
"Index too large");
805 return operator[](index);
817 T&
at(size_type index) {
818#if defined(__cpp_exceptions)
819 if (index >= size_.load(std::memory_order_relaxed)) {
820 throw std::out_of_range(
"Index too large");
823 return operator[](index);
834 return {
this, 0, {0, 0, firstBucketLen_}};
846 size_t curSize = size_.load(std::memory_order_relaxed);
847 auto binfo = bucketAndSubIndex(curSize);
848 return {
this, curSize, binfo};
859 return {
this, 0, {0, 0, firstBucketLen_}};
870 const_iterator
end()
const {
871 size_t curSize = size_.load(std::memory_order_relaxed);
872 auto binfo = bucketAndSubIndex(curSize);
873 return {
this, curSize, binfo};
884 return {
this, 0, {0, 0, firstBucketLen_}};
896 size_t curSize = size_.load(std::memory_order_relaxed);
897 auto binfo = bucketAndSubIndex(curSize);
898 return {
this, curSize, binfo};
910 return reverse_iterator(
end());
921 return reverse_iterator(
begin());
933 return const_reverse_iterator(
cend());
943 const_reverse_iterator
rend()
const {
944 return const_reverse_iterator(
cbegin());
953 return size_.load(std::memory_order_relaxed) == 0;
962 return Traits::kMaxVectorSize;
971 return size_.load(std::memory_order_relaxed);
979 return *buffers_[0].load(std::memory_order_relaxed);
987 return *buffers_[0].load(std::memory_order_relaxed);
1005 return *(
end() - 1);
1014 swap(firstBucketShift_, oth.firstBucketShift_);
1015 swap(firstBucketLen_, oth.firstBucketLen_);
1016 size_t othlen = oth.size_.load(std::memory_order_relaxed);
1017 oth.size_.store(size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
1018 size_.store(othlen, std::memory_order_relaxed);
1021 buffers_ = std::move(oth.buffers_);
1022 swapCachedPtrs(oth);
1026 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndexForIndex(
size_t index)
const {
1027#if defined(_MSC_VER) || defined(__aarch64__) || defined(_M_ARM64)
1030 if (index < firstBucketLen_) {
1031 return {0, index, firstBucketLen_};
1034 size_t l2idx = detail::log2(index);
1035 size_t bucket = (l2idx + 1) - firstBucketShift_;
1036 size_t bucketCapacity =
size_t{1} << l2idx;
1037 size_t bucketIndex = index - bucketCapacity;
1039 return {bucket, bucketIndex, bucketCapacity};
1041 return bucketAndSubIndex(index);
1045 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndex(
size_t index)
const {
1046 size_t l2idx = detail::log2(index | 1);
1047 size_t bucket = (l2idx + 1) - firstBucketShift_;
1048 size_t bucketCapacity =
size_t{1} << l2idx;
1049 size_t bucketIndex = index - bucketCapacity;
1051 bucket = index < firstBucketLen_ ? 0 : bucket;
1052 bucketIndex = index < firstBucketLen_ ? index : bucketIndex;
1053 bucketCapacity = index < firstBucketLen_ ? firstBucketLen_ : bucketCapacity;
1055 return {bucket, bucketIndex, bucketCapacity};
1058 template <
typename InIterator>
1059 void internalInit(InIterator start, InIterator
end, iterator it) {
1060 while (start !=
end) {
1061 new (&*it) T(*start);
1067 void internalFillN(iterator it,
size_t len,
const T& value) {
1068 for (; len--; ++it) {
1069 new (&*it) T(value);
1073 void internalFillDefaultN(iterator it,
size_t len) {
1074 for (; len--; ++it) {
1079 iterator growByUninitialized(size_type delta) {
1080 auto index = size_.fetch_add(delta, std::memory_order_relaxed);
1081 auto binfo = bucketAndSubIndex(index);
1082 auto bend = bucketAndSubIndex(index + delta);
1083 allocateBufferRange(binfo, delta, bend);
1084 return {
this, index, binfo};
1087 iterator insertPartial(const_iterator pos) {
1089 auto index = size_.fetch_add(1, std::memory_order_relaxed);
1090 auto binfo = bucketAndSubIndex(index);
1091 allocateBuffer(binfo);
1093 return std::move_backward(pos, const_iterator(e), e + 1) - 1;
1096 iterator insertPartial(const_iterator pos,
size_t len) {
1098 auto index = size_.fetch_add(len, std::memory_order_relaxed);
1099 auto binfo = bucketAndSubIndex(index);
1100 auto bend = bucketAndSubIndex(index + len);
1101 allocateBufferRange(binfo, len, bend);
1102 for (
auto it = e + len; it != e;) {
1106 return std::move_backward(pos, const_iterator(e), e + len) - len;
1111 SizeTraits::kDefaultCapacity / 2,
1112 SizeTraits::kMaxVectorSize,
1113 Traits::kPreferBuffersInline,
1114 Traits::kReallocStrategy> buffers_;
1116 static constexpr size_t kMaxBuffers =
1117 detail::log2const(SizeTraits::kMaxVectorSize / (SizeTraits::kDefaultCapacity / 2)) + 1;
1119#if DISPENSO_HAS_CACHED_PTRS
1128 size_t firstBucketShift_;
1129 size_t firstBucketLen_;
1133 DISPENSO_INLINE T* cachedBuffer(
size_t bucket)
const {
1134#if DISPENSO_HAS_CACHED_PTRS
1135 return cachedPtrs_[bucket];
1142 return buffers_[bucket].load(std::memory_order_relaxed);
1146 DISPENSO_INLINE
void allocateBuffer(
const cv::BucketInfo& binfo) {
1147#if DISPENSO_HAS_CACHED_PTRS
1148 buffers_.allocAsNecessary(binfo, cachedPtrs_);
1150 buffers_.allocAsNecessary(binfo);
1154 DISPENSO_INLINE
void
1155 allocateBufferRange(
const cv::BucketInfo& binfo, ssize_t rangeLen,
const cv::BucketInfo& bend) {
1156#if DISPENSO_HAS_CACHED_PTRS
1157 buffers_.allocAsNecessary(binfo, rangeLen, bend, cachedPtrs_);
1159 buffers_.allocAsNecessary(binfo, rangeLen, bend);
1163 DISPENSO_INLINE
void initCachedPtrs() {
1164#if DISPENSO_HAS_CACHED_PTRS
1165 for (
size_t i = 0; i < kMaxBuffers; ++i) {
1166 cachedPtrs_[i] =
nullptr;
1171 DISPENSO_INLINE
void setCachedPtr(
size_t bucket, T* ptr) {
1172#if DISPENSO_HAS_CACHED_PTRS
1173 cachedPtrs_[bucket] = ptr;
1180 DISPENSO_INLINE
void clearCachedPtr(
size_t bucket) {
1181#if DISPENSO_HAS_CACHED_PTRS
1182 cachedPtrs_[bucket] =
nullptr;
1189#if DISPENSO_HAS_CACHED_PTRS
1190 for (
size_t i = 0; i < kMaxBuffers; ++i) {
1191 cachedPtrs_[i] = other.cachedPtrs_[i];
1192 other.cachedPtrs_[i] =
nullptr;
1200#if DISPENSO_HAS_CACHED_PTRS
1201 for (
size_t i = 0; i < kMaxBuffers; ++i) {
1202 T* cur = cachedPtrs_[i];
1203 cachedPtrs_[i] = other.cachedPtrs_[i];
1204 other.cachedPtrs_[i] = cur;
1212 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, false>;
1213 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, true>;