190 using value_type = T;
191 using reference = T&;
192 using const_reference =
const T&;
193 using size_type = size_t;
194 using difference_type = ssize_t;
195 using reference_type = T&;
196 using const_reference_type =
const T&;
198 using const_pointer =
const T*;
199 using iterator = std::conditional_t<
200 Traits::kIteratorPreferSpeed,
201 cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T,
false>,
202 cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T,
false>>;
203 using const_iterator = std::conditional_t<
204 Traits::kIteratorPreferSpeed,
205 cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T,
true>,
206 cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T,
true>>;
207 using reverse_iterator = std::reverse_iterator<iterator>;
208 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
223 detail::
nextPow2(std::max(startCapacity, SizeTraits::kDefaultCapacity / 2)))),
224 firstBucketLen_(size_type{1} << firstBucketShift_) {
225 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
227 setCachedPtr(0, firstTwo);
228 setCachedPtr(1, firstTwo + firstBucketLen_);
229 buffers_[0].store(firstTwo, std::memory_order_release);
230 buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_release);
237 T* buf = buffers_[0].load(std::memory_order_relaxed);
238 SizeOnExit constructed{size_, 0};
239 for (; constructed.count < startSize; ++constructed.count) {
240 new (buf + constructed.count) T();
249 T* buf = buffers_[0].load(std::memory_order_relaxed);
250 SizeOnExit constructed{size_, 0};
251 for (; constructed.count < startSize; ++constructed.count) {
252 new (buf + constructed.count) T(defaultValue);
259 template <
typename InIterator,
typename = cv::EnableIfInputIterator<InIterator>>
268 template <
typename InIterator,
typename = cv::EnableIfInputIterator<InIterator>>
271 assert(cv::rangeLengthIs(start,
end, startSize, cv::IteratorCategory<InIterator>{}));
272 initFromEmpty(start,
end);
291 : buffers_(std::move(other.buffers_)),
292 firstBucketShift_(other.firstBucketShift_),
293 firstBucketLen_(other.firstBucketLen_),
294 gaps_(other.gaps_.exchange(nullptr, std::memory_order_relaxed)),
295 size_(other.size_.load(std::memory_order_relaxed)) {
296 moveCachedPtrsFrom(other);
297 other.size_.store(0, std::memory_order_relaxed);
300 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
301 other.setCachedPtr(0, firstTwo);
302 other.setCachedPtr(1, firstTwo + firstBucketLen_);
303 other.buffers_[0].store(firstTwo, std::memory_order_relaxed);
304 other.buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_relaxed);
311 if (&other ==
this) {
327 if (&other ==
this) {
332 swap(firstBucketShift_, other.firstBucketShift_);
333 swap(firstBucketLen_, other.firstBucketLen_);
334 buffers_ = std::move(other.buffers_);
335 swapCachedPtrs(other);
337 size_t curLen = size_.load(std::memory_order_relaxed);
338 size_.store(other.size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
339 other.size_.store(curLen, std::memory_order_relaxed);
350 void assign(size_type count,
const T& value) {
353 SizeOnExit constructed{size_, 0};
354 for (iterator it =
begin(); constructed.count < count; ++it, ++constructed.count) {
367 typename =
typename std::iterator_traits<It>::difference_type,
368 typename =
typename std::iterator_traits<It>::pointer,
369 typename =
typename std::iterator_traits<It>::reference,
370 typename =
typename std::iterator_traits<It>::value_type,
371 typename =
typename std::iterator_traits<It>::iterator_category>
374 assignRange(start,
end, cv::IteratorCategory<It>{});
383 auto bend = bucketAndSubIndex(
capacity);
384 allocateBufferRange({0, 0, firstBucketLen_},
capacity, bend);
393 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
396 }
else if (curLen > len) {
398 auto newEnd =
begin() + len;
402 }
while (it != newEnd);
403 size_.store(len, std::memory_order_relaxed);
413 void resize(difference_type len,
const T& value) {
414 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
417 }
else if (curLen > len) {
419 auto newEnd =
begin() + len;
423 }
while (it != newEnd);
424 size_.store(len, std::memory_order_relaxed);
433 return 2 * firstBucketLen_;
441 size_t cap = 2 * firstBucketLen_;
442 for (
size_t b = 2; b < kMaxBuffers; ++b) {
443 if (!buffers_[b].load(std::memory_order_relaxed)) {
456#if defined(__cpp_exceptions)
457 if (DISPENSO_EXPECT(gaps_.load(std::memory_order_relaxed) !=
nullptr,
false)) {
462 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
463 size_t len = binfo.bucketIndex;
464 size_t cap = binfo.bucketCapacity;
465 size_t b = binfo.bucket;
467 T* buf = buffers_[b].load(std::memory_order_relaxed);
477 size_.store(0, std::memory_order_release);
485 constexpr size_t kMaxExtra = 2;
486 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
489 size_t startBucket = std::max<size_t>(2, binfo.bucket + kMaxExtra);
491 for (
size_t b = startBucket; b < kMaxBuffers; ++b) {
492 T* ptr = buffers_[b].load(std::memory_order_relaxed);
496 if (buffers_.shouldDealloc(b)) {
500 buffers_[b].store(
nullptr, std::memory_order_release);
510 cv::dealloc<T>(buffers_[0].load(std::memory_order_acquire));
519 iterator
insert(const_iterator pos,
const T& value) {
520 auto it = insertPartial(pos);
533 iterator
insert(const_iterator pos, T&& value) {
534 auto it = insertPartial(pos);
535 *it = std::move(value);
546 iterator
insert(const_iterator pos, size_type count,
const T& value) {
547 auto it = insertPartial(pos, count);
548 std::fill_n(it, count, value);
561 typename =
typename std::iterator_traits<InputIt>::difference_type,
562 typename =
typename std::iterator_traits<InputIt>::pointer,
563 typename =
typename std::iterator_traits<InputIt>::reference,
564 typename =
typename std::iterator_traits<InputIt>::value_type,
565 typename =
typename std::iterator_traits<InputIt>::iterator_category>
566 iterator
insert(const_iterator pos, InputIt first, InputIt last) {
567 return insertRange(pos, first, last, cv::IteratorCategory<InputIt>{});
576 iterator
insert(const_iterator pos, std::initializer_list<T> ilist) {
577 return insert(pos, ilist.begin(), ilist.end());
586 iterator
erase(const_iterator pos) {
591 size_.fetch_sub(1, std::memory_order_relaxed);
599 it = std::move(pos + 1, const_iterator(e + 1), it);
613 iterator
erase(const_iterator first, const_iterator last) {
614 size_t len = std::distance(first, last);
616 size_t startIdx = first - it;
618 return it + (startIdx + len);
623 auto e_it = std::move(last, const_iterator(e), it);
631 size_.fetch_sub(len, std::memory_order_relaxed);
658 template <
typename... Args>
660 auto index = size_.fetch_add(1, std::memory_order_relaxed);
661 auto binfo = bucketAndSubIndex(index);
663 allocateBuffer(binfo);
665 iterator ret{
this, index, binfo};
667 T* slot = Traits::kIteratorPreferSpeed ? &*ret : buffers_[binfo.bucket] + binfo.bucketIndex;
668#if defined(__cpp_exceptions)
670 new (slot) T(std::forward<Args>(args)...);
672 finishFailedGrowth(ret, 1);
676 new (slot) T(std::forward<Args>(args)...);
689 template <
typename Gen>
691 iterator ret = growByUninitialized(delta);
692 constructGrown(ret, delta, [&gen](T* p) {
new (p) T(gen()); });
702 iterator
grow_by(size_type delta,
const T& t) {
703 iterator ret = growByUninitialized(delta);
704 internalFillN(ret, delta, t);
714 iterator ret = growByUninitialized(delta);
715 internalFillDefaultN(ret, delta);
727 typename =
typename std::iterator_traits<It>::difference_type,
728 typename =
typename std::iterator_traits<It>::pointer,
729 typename =
typename std::iterator_traits<It>::reference,
730 typename =
typename std::iterator_traits<It>::value_type,
731 typename =
typename std::iterator_traits<It>::iterator_category>
733 return growByRange(start,
end, cv::IteratorCategory<It>{});
741 iterator
grow_by(std::initializer_list<T> initList) {
742 return grow_by(std::begin(initList), std::end(initList));
752 size_t curSize = size_.load(std::memory_order_relaxed);
756 return {
this, n - 1, bucketAndSubIndex(n - 1)};
767 size_t curSize = size_.load(std::memory_order_relaxed);
769 return grow_by(n - curSize, t);
771 return {
this, n - 1, bucketAndSubIndex(n - 1)};
778 auto binfo = bucketAndSubIndex(size_.fetch_sub(1, std::memory_order_relaxed) - 1);
779 T* elt = buffers_[binfo.bucket].load(std::memory_order_relaxed) + binfo.bucketIndex;
791 const T& operator[](size_type index)
const {
792 auto binfo = bucketAndSubIndexForIndex(index);
793 T* buf = cachedBuffer(binfo.bucket);
794 return buf[binfo.bucketIndex];
805 T& operator[](size_type index) {
806 auto binfo = bucketAndSubIndexForIndex(index);
807 T* buf = cachedBuffer(binfo.bucket);
808 return buf[binfo.bucketIndex];
820 const T&
at(size_type index)
const {
821#if defined(__cpp_exceptions)
822 if (index >= size_.load(std::memory_order_relaxed)) {
823 throw std::out_of_range(
"Index too large");
826 return operator[](index);
838 T&
at(size_type index) {
839#if defined(__cpp_exceptions)
840 if (index >= size_.load(std::memory_order_relaxed)) {
841 throw std::out_of_range(
"Index too large");
844 return operator[](index);
855 return {
this, 0, {0, 0, firstBucketLen_}};
867 size_t curSize = size_.load(std::memory_order_relaxed);
868 auto binfo = bucketAndSubIndex(curSize);
869 return {
this, curSize, binfo};
880 return {
this, 0, {0, 0, firstBucketLen_}};
891 const_iterator
end()
const {
892 size_t curSize = size_.load(std::memory_order_relaxed);
893 auto binfo = bucketAndSubIndex(curSize);
894 return {
this, curSize, binfo};
905 return {
this, 0, {0, 0, firstBucketLen_}};
917 size_t curSize = size_.load(std::memory_order_relaxed);
918 auto binfo = bucketAndSubIndex(curSize);
919 return {
this, curSize, binfo};
931 return reverse_iterator(
end());
942 return reverse_iterator(
begin());
954 return const_reverse_iterator(
cend());
964 const_reverse_iterator
rend()
const {
965 return const_reverse_iterator(
cbegin());
974 return size_.load(std::memory_order_relaxed) == 0;
983 return Traits::kMaxVectorSize;
992 return size_.load(std::memory_order_relaxed);
1000 return *buffers_[0].load(std::memory_order_relaxed);
1008 return *buffers_[0].load(std::memory_order_relaxed);
1017 return *(
end() - 1);
1026 return *(
end() - 1);
1035 swap(firstBucketShift_, oth.firstBucketShift_);
1036 swap(firstBucketLen_, oth.firstBucketLen_);
1037 size_t othlen = oth.size_.load(std::memory_order_relaxed);
1038 oth.size_.store(size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
1039 size_.store(othlen, std::memory_order_relaxed);
1042 buffers_ = std::move(oth.buffers_);
1043 swapCachedPtrs(oth);
1051 template <
typename It>
1055 template <
typename It>
1057 for (; start !=
end; ++start) {
1062 template <
typename It>
1063 void assignRange(It start, It
end, std::forward_iterator_tag) {
1065 initFromEmpty(start,
end);
1068 template <
typename It>
1069 void assignRange(It start, It
end, std::input_iterator_tag) {
1070 for (; start !=
end; ++start) {
1075 template <
typename It>
1076 iterator insertRange(const_iterator pos, It first, It last, std::forward_iterator_tag) {
1077 size_t len = std::distance(first, last);
1078 auto it = insertPartial(pos, len);
1079 std::copy_n(first, len, it);
1083 template <
typename It>
1084 iterator insertRange(const_iterator pos, It first, It last, std::input_iterator_tag) {
1086 const difference_type index = pos -
cbegin();
1087 const difference_type oldSize =
static_cast<difference_type
>(
size());
1088 for (; first != last; ++first) {
1092 std::rotate(b + index, b + oldSize,
end());
1096 template <
typename It>
1097 iterator growByRange(It start, It
end, std::forward_iterator_tag) {
1098 const size_t len =
static_cast<size_t>(std::distance(start,
end));
1099 iterator ret = growByUninitialized(len);
1100 internalInit(start, ret, len);
1104 template <
typename It>
1105 iterator growByRange(It start, It
end, std::input_iterator_tag) {
1110 std::vector<T> buffered(start,
end);
1112 std::make_move_iterator(buffered.begin()),
1113 std::make_move_iterator(buffered.end()),
1114 std::random_access_iterator_tag{});
1117 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndexForIndex(
size_t index)
const {
1118#if defined(_MSC_VER) || defined(__aarch64__) || defined(_M_ARM64)
1121 if (index < firstBucketLen_) {
1122 return {0, index, firstBucketLen_};
1125 size_t l2idx = detail::log2(index);
1126 size_t bucket = (l2idx + 1) - firstBucketShift_;
1127 size_t bucketCapacity =
size_t{1} << l2idx;
1128 size_t bucketIndex = index - bucketCapacity;
1130 return {bucket, bucketIndex, bucketCapacity};
1132 return bucketAndSubIndex(index);
1136 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndex(
size_t index)
const {
1137 size_t l2idx = detail::log2(index | 1);
1138 size_t bucket = (l2idx + 1) - firstBucketShift_;
1139 size_t bucketCapacity =
size_t{1} << l2idx;
1140 size_t bucketIndex = index - bucketCapacity;
1142 bucket = index < firstBucketLen_ ? 0 : bucket;
1143 bucketIndex = index < firstBucketLen_ ? index : bucketIndex;
1144 bucketCapacity = index < firstBucketLen_ ? firstBucketLen_ : bucketCapacity;
1146 return {bucket, bucketIndex, bucketCapacity};
1153 std::atomic<size_t>& size;
1156 size.store(count, std::memory_order_relaxed);
1160#if defined(__cpp_exceptions)
1169 void finishFailedGrowth(
const iterator& it,
size_t count) {
1170 finishFailedGrowth(it, count, std::is_nothrow_default_constructible<T>{});
1173 void finishFailedGrowth(
const iterator& first,
size_t count, std::true_type)
noexcept {
1174 for (iterator it = first; count--; ++it) {
1181 void finishFailedGrowth(
const iterator& it,
size_t count, std::false_type) {
1182 const size_t first =
static_cast<size_t>(it -
begin());
1183 Gap* gap =
new Gap{first, first + count, gaps_.load(std::memory_order_relaxed)};
1184 while (!gaps_.compare_exchange_weak(
1185 gap->next, gap, std::memory_order_release, std::memory_order_relaxed)) {
1191 void clearWithGaps() {
1193 Gap* sorted =
nullptr;
1194 Gap* gap = gaps_.exchange(
nullptr, std::memory_order_acquire);
1196 Gap* next = gap->next;
1197 Gap** pos = &sorted;
1198 while (*pos && (*pos)->first > gap->first) {
1199 pos = &(*pos)->next;
1206 size_t index = size_.load(std::memory_order_relaxed);
1208 if (sorted && index == sorted->last) {
1209 index = sorted->first;
1211 sorted = sorted->next;
1216 auto binfo = bucketAndSubIndex(index);
1217 (buffers_[binfo.bucket].load(std::memory_order_relaxed) + binfo.bucketIndex)->~T();
1219 size_.store(0, std::memory_order_release);
1230 template <
typename Construct>
1231 void constructGrown(iterator it,
size_t len, Construct&& construct) {
1232#if defined(__cpp_exceptions)
1235 for (; built < len; ++built, ++it) {
1239 finishFailedGrowth(it, len - built);
1243 for (; len--; ++it) {
1250#if defined(__cpp_exceptions)
1251 Gap* mine = gaps_.load(std::memory_order_relaxed);
1252 gaps_.store(other.gaps_.load(std::memory_order_relaxed), std::memory_order_relaxed);
1253 other.gaps_.store(mine, std::memory_order_relaxed);
1260 template <
typename InIterator>
1261 void initFromEmpty(InIterator start, InIterator
end) {
1262 SizeOnExit constructed{size_, 0};
1263 for (iterator it =
begin(); start !=
end; ++it, ++start, ++constructed.count) {
1264 new (&*it) T(*start);
1269 template <
typename InIterator>
1270 void internalInit(InIterator start, iterator it,
size_t len) {
1271 constructGrown(it, len, [&start](T* p) {
1277 void internalFillN(iterator it,
size_t len,
const T& value) {
1278 constructGrown(it, len, [&value](T* p) {
new (p) T(value); });
1281 void internalFillDefaultN(iterator it,
size_t len) {
1282 constructGrown(it, len, [](T* p) {
new (p) T(); });
1285 iterator growByUninitialized(size_type delta) {
1286 auto index = size_.fetch_add(delta, std::memory_order_relaxed);
1287 auto binfo = bucketAndSubIndex(index);
1288 auto bend = bucketAndSubIndex(index + delta);
1289 allocateBufferRange(binfo, delta, bend);
1290 return {
this, index, binfo};
1293 iterator insertPartial(const_iterator pos) {
1295 auto index = size_.fetch_add(1, std::memory_order_relaxed);
1296 auto binfo = bucketAndSubIndex(index);
1297 allocateBuffer(binfo);
1298 internalFillDefaultN(e, 1);
1299 return std::move_backward(pos, const_iterator(e), e + 1) - 1;
1302 iterator insertPartial(const_iterator pos,
size_t len) {
1304 auto index = size_.fetch_add(len, std::memory_order_relaxed);
1305 auto binfo = bucketAndSubIndex(index);
1306 auto bend = bucketAndSubIndex(index + len);
1307 allocateBufferRange(binfo, len, bend);
1308 internalFillDefaultN(e, len);
1309 return std::move_backward(pos, const_iterator(e), e + len) - len;
1314 SizeTraits::kDefaultCapacity / 2,
1315 SizeTraits::kMaxVectorSize,
1316 Traits::kPreferBuffersInline,
1317 Traits::kReallocStrategy> buffers_;
1319 static constexpr size_t kMaxBuffers =
1320 detail::log2const(SizeTraits::kMaxVectorSize / (SizeTraits::kDefaultCapacity / 2)) + 1;
1322#if DISPENSO_HAS_CACHED_PTRS
1331 size_t firstBucketShift_;
1332 size_t firstBucketLen_;
1337 std::atomic<Gap*> gaps_{
nullptr};
1341 DISPENSO_INLINE T* cachedBuffer(
size_t bucket)
const {
1342#if DISPENSO_HAS_CACHED_PTRS
1343 return cachedPtrs_[bucket];
1350 return buffers_[bucket].load(std::memory_order_relaxed);
1354 DISPENSO_INLINE
void allocateBuffer(
const cv::BucketInfo& binfo) {
1355#if DISPENSO_HAS_CACHED_PTRS
1356 buffers_.allocAsNecessary(binfo, cachedPtrs_);
1358 buffers_.allocAsNecessary(binfo);
1362 DISPENSO_INLINE
void
1363 allocateBufferRange(
const cv::BucketInfo& binfo, ssize_t rangeLen,
const cv::BucketInfo& bend) {
1364#if DISPENSO_HAS_CACHED_PTRS
1365 buffers_.allocAsNecessary(binfo, rangeLen, bend, cachedPtrs_);
1367 buffers_.allocAsNecessary(binfo, rangeLen, bend);
1371 DISPENSO_INLINE
void initCachedPtrs() {
1372#if DISPENSO_HAS_CACHED_PTRS
1373 for (
size_t i = 0; i < kMaxBuffers; ++i) {
1374 cachedPtrs_[i] =
nullptr;
1379 DISPENSO_INLINE
void setCachedPtr(
size_t bucket, T* ptr) {
1380#if DISPENSO_HAS_CACHED_PTRS
1381 cachedPtrs_[bucket] = ptr;
1388 DISPENSO_INLINE
void clearCachedPtr(
size_t bucket) {
1389#if DISPENSO_HAS_CACHED_PTRS
1390 cachedPtrs_[bucket] =
nullptr;
1397#if DISPENSO_HAS_CACHED_PTRS
1398 for (
size_t i = 0; i < kMaxBuffers; ++i) {
1399 cachedPtrs_[i] = other.cachedPtrs_[i];
1400 other.cachedPtrs_[i] =
nullptr;
1408#if DISPENSO_HAS_CACHED_PTRS
1409 for (
size_t i = 0; i < kMaxBuffers; ++i) {
1410 T* cur = cachedPtrs_[i];
1411 cachedPtrs_[i] = other.cachedPtrs_[i];
1412 other.cachedPtrs_[i] = cur;
1420 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, false>;
1421 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, true>;