179 using value_type = T;
180 using reference = T&;
181 using const_reference =
const T&;
182 using size_type = size_t;
183 using difference_type = ssize_t;
184 using reference_type = T&;
185 using const_reference_type =
const T&;
187 using const_pointer =
const T*;
188 using iterator = std::conditional_t<
189 Traits::kIteratorPreferSpeed,
190 cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T,
false>,
191 cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T,
false>>;
192 using const_iterator = std::conditional_t<
193 Traits::kIteratorPreferSpeed,
194 cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T,
true>,
195 cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T,
true>>;
196 using reverse_iterator = std::reverse_iterator<iterator>;
197 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
212 detail::
nextPow2(std::max(startCapacity, SizeTraits::kDefaultCapacity / 2)))),
213 firstBucketLen_(size_type{1} << firstBucketShift_) {
214 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
216 setCachedPtr(0, firstTwo);
217 setCachedPtr(1, firstTwo + firstBucketLen_);
218 buffers_[0].store(firstTwo, std::memory_order_release);
219 buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_release);
226 size_.store(startSize, std::memory_order_relaxed);
227 T* buf = buffers_[0].load(std::memory_order_relaxed);
228 for (
size_t i = 0; i < startSize; ++i) {
238 size_.store(startSize, std::memory_order_relaxed);
239 T* buf = buffers_[0].load(std::memory_order_relaxed);
240 for (
size_t i = 0; i < startSize; ++i) {
241 new (buf + i) T(defaultValue);
248 template <
typename InIterator>
257 template <
typename InIterator>
260 size_.store(startSize, std::memory_order_relaxed);
261 assert(std::distance(start,
end) ==
static_cast<difference_type
>(startSize));
281 : buffers_(std::move(other.buffers_)),
282 firstBucketShift_(other.firstBucketShift_),
283 firstBucketLen_(other.firstBucketLen_),
284 size_(other.size_.load(std::memory_order_relaxed)) {
285 moveCachedPtrsFrom(other);
286 other.size_.store(0, std::memory_order_relaxed);
289 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
290 other.setCachedPtr(0, firstTwo);
291 other.setCachedPtr(1, firstTwo + firstBucketLen_);
292 other.buffers_[0].store(firstTwo, std::memory_order_relaxed);
293 other.buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_relaxed);
300 if (&other ==
this) {
306 size_.store(other.
size(), std::memory_order_relaxed);
317 if (&other ==
this) {
322 swap(firstBucketShift_, other.firstBucketShift_);
323 swap(firstBucketLen_, other.firstBucketLen_);
324 buffers_ = std::move(other.buffers_);
325 swapCachedPtrs(other);
326 size_t curLen = size_.load(std::memory_order_relaxed);
327 size_.store(other.size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
328 other.size_.store(curLen, std::memory_order_relaxed);
339 void assign(size_type count,
const T& value) {
342 size_.store(count, std::memory_order_relaxed);
343 internalFillN(
begin(), count, value);
354 typename =
typename std::iterator_traits<It>::difference_type,
355 typename =
typename std::iterator_traits<It>::pointer,
356 typename =
typename std::iterator_traits<It>::reference,
357 typename =
typename std::iterator_traits<It>::value_type,
358 typename =
typename std::iterator_traits<It>::iterator_category>
361 auto count = std::distance(start,
end);
363 size_.store(count, std::memory_order_relaxed);
373 auto bend = bucketAndSubIndex(
capacity);
374 allocateBufferRange({0, 0, firstBucketLen_},
capacity, bend);
383 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
386 }
else if (curLen > len) {
388 auto newEnd =
begin() + len;
392 }
while (it != newEnd);
393 size_.store(len, std::memory_order_relaxed);
403 void resize(difference_type len,
const T& value) {
404 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
407 }
else if (curLen > len) {
409 auto newEnd =
begin() + len;
413 }
while (it != newEnd);
414 size_.store(len, std::memory_order_relaxed);
423 return 2 * firstBucketLen_;
431 size_t cap = 2 * firstBucketLen_;
432 for (
size_t b = 2; b < kMaxBuffers; ++b) {
433 if (!buffers_[b].load(std::memory_order_relaxed)) {
446 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
447 size_t len = binfo.bucketIndex;
448 size_t cap = binfo.bucketCapacity;
449 size_t b = binfo.bucket;
451 T* buf = buffers_[b].load(std::memory_order_relaxed);
461 size_.store(0, std::memory_order_release);
469 constexpr size_t kMaxExtra = 2;
470 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
473 size_t startBucket = std::max<size_t>(2, binfo.bucket + kMaxExtra);
475 for (
size_t b = startBucket; b < kMaxBuffers; ++b) {
476 T* ptr = buffers_[b].load(std::memory_order_relaxed);
480 if (buffers_.shouldDealloc(b)) {
484 buffers_[b].store(
nullptr, std::memory_order_release);
494 cv::dealloc<T>(buffers_[0].load(std::memory_order_acquire));
503 iterator
insert(const_iterator pos,
const T& value) {
504 auto it = insertPartial(pos);
515 iterator
insert(const_iterator pos, T&& value) {
516 auto it = insertPartial(pos);
517 new (&*it) T(std::move(value));
528 iterator
insert(const_iterator pos, size_type count,
const T& value) {
529 auto it = insertPartial(pos, count);
530 std::fill_n(it, count, value);
543 typename =
typename std::iterator_traits<InputIt>::difference_type,
544 typename =
typename std::iterator_traits<InputIt>::pointer,
545 typename =
typename std::iterator_traits<InputIt>::reference,
546 typename =
typename std::iterator_traits<InputIt>::value_type,
547 typename =
typename std::iterator_traits<InputIt>::iterator_category>
548 iterator
insert(const_iterator pos, InputIt first, InputIt last) {
549 size_t len = std::distance(first, last);
550 auto it = insertPartial(pos, len);
551 std::copy_n(first, len, it);
561 iterator
insert(const_iterator pos, std::initializer_list<T> ilist) {
562 return insert(pos, ilist.begin(), ilist.end());
571 iterator
erase(const_iterator pos) {
576 size_.fetch_sub(1, std::memory_order_relaxed);
585 return std::move(pos + 1, const_iterator(e), it);
596 iterator
erase(const_iterator first, const_iterator last) {
597 size_t len = std::distance(first, last);
599 size_t startIdx = first - it;
601 return it + (startIdx + len);
605 auto e_it = std::move(last,
cend(), it);
612 }
while (e_it != last);
614 size_.fetch_sub(len, std::memory_order_relaxed);
641 template <
typename... Args>
643 auto index = size_.fetch_add(1, std::memory_order_relaxed);
644 auto binfo = bucketAndSubIndex(index);
646 allocateBuffer(binfo);
648 iterator ret{
this, index, binfo};
650 if (Traits::kIteratorPreferSpeed) {
651 new (&*ret) T(std::forward<Args>(args)...);
653 new (buffers_[binfo.bucket] + binfo.bucketIndex) T(std::forward<Args>(args)...);
666 template <
typename Gen>
668 iterator ret = growByUninitialized(delta);
669 for (
auto it = ret; delta--; ++it) {
681 iterator
grow_by(size_type delta,
const T& t) {
682 iterator ret = growByUninitialized(delta);
683 internalFillN(ret, delta, t);
693 iterator ret = growByUninitialized(delta);
694 internalFillDefaultN(ret, delta);
706 typename =
typename std::iterator_traits<It>::difference_type,
707 typename =
typename std::iterator_traits<It>::pointer,
708 typename =
typename std::iterator_traits<It>::reference,
709 typename =
typename std::iterator_traits<It>::value_type,
710 typename =
typename std::iterator_traits<It>::iterator_category>
712 iterator ret = growByUninitialized(std::distance(start,
end));
713 internalInit(start,
end, ret);
722 iterator
grow_by(std::initializer_list<T> initList) {
723 return grow_by(std::begin(initList), std::end(initList));
733 size_t curSize = size_.load(std::memory_order_relaxed);
737 return {
this, n - 1, bucketAndSubIndex(n - 1)};
748 size_t curSize = size_.load(std::memory_order_relaxed);
750 return grow_by(n - curSize, t);
752 return {
this, n - 1, bucketAndSubIndex(n - 1)};
759 auto binfo = bucketAndSubIndex(size_.fetch_sub(1, std::memory_order_relaxed) - 1);
760 T* elt = buffers_[binfo.bucket].load(std::memory_order_relaxed) + binfo.bucketIndex;
772 const T& operator[](size_type index)
const {
773 auto binfo = bucketAndSubIndexForIndex(index);
774 T* buf = cachedBuffer(binfo.bucket);
775 return buf[binfo.bucketIndex];
786 T& operator[](size_type index) {
787 auto binfo = bucketAndSubIndexForIndex(index);
788 T* buf = cachedBuffer(binfo.bucket);
789 return buf[binfo.bucketIndex];
801 const T&
at(size_type index)
const {
802#if defined(__cpp_exceptions)
803 if (index >= size_.load(std::memory_order_relaxed)) {
804 throw std::out_of_range(
"Index too large");
807 return operator[](index);
819 T&
at(size_type index) {
820#if defined(__cpp_exceptions)
821 if (index >= size_.load(std::memory_order_relaxed)) {
822 throw std::out_of_range(
"Index too large");
825 return operator[](index);
836 return {
this, 0, {0, 0, firstBucketLen_}};
848 size_t curSize = size_.load(std::memory_order_relaxed);
849 auto binfo = bucketAndSubIndex(curSize);
850 return {
this, curSize, binfo};
861 return {
this, 0, {0, 0, firstBucketLen_}};
872 const_iterator
end()
const {
873 size_t curSize = size_.load(std::memory_order_relaxed);
874 auto binfo = bucketAndSubIndex(curSize);
875 return {
this, curSize, binfo};
886 return {
this, 0, {0, 0, firstBucketLen_}};
898 size_t curSize = size_.load(std::memory_order_relaxed);
899 auto binfo = bucketAndSubIndex(curSize);
900 return {
this, curSize, binfo};
912 return reverse_iterator(
end());
923 return reverse_iterator(
begin());
935 return const_reverse_iterator(
cend());
945 const_reverse_iterator
rend()
const {
946 return const_reverse_iterator(
cbegin());
955 return size_.load(std::memory_order_relaxed) == 0;
964 return Traits::kMaxVectorSize;
973 return size_.load(std::memory_order_relaxed);
981 return *buffers_[0].load(std::memory_order_relaxed);
989 return *buffers_[0].load(std::memory_order_relaxed);
1007 return *(
end() - 1);
1016 swap(firstBucketShift_, oth.firstBucketShift_);
1017 swap(firstBucketLen_, oth.firstBucketLen_);
1018 size_t othlen = oth.size_.load(std::memory_order_relaxed);
1019 oth.size_.store(size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
1020 size_.store(othlen, std::memory_order_relaxed);
1023 buffers_ = std::move(oth.buffers_);
1024 swapCachedPtrs(oth);
1028 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndexForIndex(
size_t index)
const {
1029#if defined(_MSC_VER) || defined(__aarch64__) || defined(_M_ARM64)
1032 if (index < firstBucketLen_) {
1033 return {0, index, firstBucketLen_};
1036 size_t l2idx = detail::log2(index);
1037 size_t bucket = (l2idx + 1) - firstBucketShift_;
1038 size_t bucketCapacity =
size_t{1} << l2idx;
1039 size_t bucketIndex = index - bucketCapacity;
1041 return {bucket, bucketIndex, bucketCapacity};
1043 return bucketAndSubIndex(index);
1047 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndex(
size_t index)
const {
1048 size_t l2idx = detail::log2(index | 1);
1049 size_t bucket = (l2idx + 1) - firstBucketShift_;
1050 size_t bucketCapacity =
size_t{1} << l2idx;
1051 size_t bucketIndex = index - bucketCapacity;
1053 bucket = index < firstBucketLen_ ? 0 : bucket;
1054 bucketIndex = index < firstBucketLen_ ? index : bucketIndex;
1055 bucketCapacity = index < firstBucketLen_ ? firstBucketLen_ : bucketCapacity;
1057 return {bucket, bucketIndex, bucketCapacity};
1060 template <
typename InIterator>
1061 void internalInit(InIterator start, InIterator
end, iterator it) {
1062 while (start !=
end) {
1063 new (&*it) T(*start);
1069 void internalFillN(iterator it,
size_t len,
const T& value) {
1070 for (; len--; ++it) {
1071 new (&*it) T(value);
1075 void internalFillDefaultN(iterator it,
size_t len) {
1076 for (; len--; ++it) {
1081 iterator growByUninitialized(size_type delta) {
1082 auto index = size_.fetch_add(delta, std::memory_order_relaxed);
1083 auto binfo = bucketAndSubIndex(index);
1084 auto bend = bucketAndSubIndex(index + delta);
1085 allocateBufferRange(binfo, delta, bend);
1086 return {
this, index, binfo};
1089 iterator insertPartial(const_iterator pos) {
1091 auto index = size_.fetch_add(1, std::memory_order_relaxed);
1092 auto binfo = bucketAndSubIndex(index);
1093 allocateBuffer(binfo);
1095 return std::move_backward(pos, const_iterator(e), e + 1) - 1;
1098 iterator insertPartial(const_iterator pos,
size_t len) {
1100 auto index = size_.fetch_add(len, std::memory_order_relaxed);
1101 auto binfo = bucketAndSubIndex(index);
1102 auto bend = bucketAndSubIndex(index + len);
1103 allocateBufferRange(binfo, len, bend);
1104 for (
auto it = e + len; it != e;) {
1108 return std::move_backward(pos, const_iterator(e), e + len) - len;
1113 SizeTraits::kDefaultCapacity / 2,
1114 SizeTraits::kMaxVectorSize,
1115 Traits::kPreferBuffersInline,
1116 Traits::kReallocStrategy> buffers_;
1118 static constexpr size_t kMaxBuffers =
1119 detail::log2const(SizeTraits::kMaxVectorSize / (SizeTraits::kDefaultCapacity / 2)) + 1;
1121#if DISPENSO_HAS_CACHED_PTRS
1130 size_t firstBucketShift_;
1131 size_t firstBucketLen_;
1135 DISPENSO_INLINE T* cachedBuffer(
size_t bucket)
const {
1136#if DISPENSO_HAS_CACHED_PTRS
1137 return cachedPtrs_[bucket];
1144 return buffers_[bucket].load(std::memory_order_relaxed);
1148 DISPENSO_INLINE
void allocateBuffer(
const cv::BucketInfo& binfo) {
1149#if DISPENSO_HAS_CACHED_PTRS
1150 buffers_.allocAsNecessary(binfo, cachedPtrs_);
1152 buffers_.allocAsNecessary(binfo);
1156 DISPENSO_INLINE
void
1157 allocateBufferRange(
const cv::BucketInfo& binfo, ssize_t rangeLen,
const cv::BucketInfo& bend) {
1158#if DISPENSO_HAS_CACHED_PTRS
1159 buffers_.allocAsNecessary(binfo, rangeLen, bend, cachedPtrs_);
1161 buffers_.allocAsNecessary(binfo, rangeLen, bend);
1165 DISPENSO_INLINE
void initCachedPtrs() {
1166#if DISPENSO_HAS_CACHED_PTRS
1167 for (
size_t i = 0; i < kMaxBuffers; ++i) {
1168 cachedPtrs_[i] =
nullptr;
1173 DISPENSO_INLINE
void setCachedPtr(
size_t bucket, T* ptr) {
1174#if DISPENSO_HAS_CACHED_PTRS
1175 cachedPtrs_[bucket] = ptr;
1182 DISPENSO_INLINE
void clearCachedPtr(
size_t bucket) {
1183#if DISPENSO_HAS_CACHED_PTRS
1184 cachedPtrs_[bucket] =
nullptr;
1191#if DISPENSO_HAS_CACHED_PTRS
1192 for (
size_t i = 0; i < kMaxBuffers; ++i) {
1193 cachedPtrs_[i] = other.cachedPtrs_[i];
1194 other.cachedPtrs_[i] =
nullptr;
1202#if DISPENSO_HAS_CACHED_PTRS
1203 for (
size_t i = 0; i < kMaxBuffers; ++i) {
1204 T* cur = cachedPtrs_[i];
1205 cachedPtrs_[i] = other.cachedPtrs_[i];
1206 other.cachedPtrs_[i] = cur;
1214 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, false>;
1215 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, true>;