160 using value_type = T;
161 using reference = T&;
162 using const_reference =
const T&;
163 using size_type = size_t;
164 using difference_type = ssize_t;
165 using reference_type = T&;
166 using const_reference_type =
const T&;
168 using const_pointer =
const T*;
169 using iterator = std::conditional_t<
170 Traits::kIteratorPreferSpeed,
171 cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T,
false>,
172 cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T,
false>>;
173 using const_iterator = std::conditional_t<
174 Traits::kIteratorPreferSpeed,
175 cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T,
true>,
176 cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T,
true>>;
177 using reverse_iterator = std::reverse_iterator<iterator>;
178 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
193 detail::
nextPow2(std::max(startCapacity, SizeTraits::kDefaultCapacity / 2)))),
194 firstBucketLen_(size_type{1} << firstBucketShift_) {
195 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
196 buffers_[0].store(firstTwo, std::memory_order_release);
197 buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_release);
204 size_.store(startSize, std::memory_order_relaxed);
205 T* buf = buffers_[0].load(std::memory_order_relaxed);
206 for (
size_t i = 0; i < startSize; ++i) {
216 size_.store(startSize, std::memory_order_relaxed);
217 T* buf = buffers_[0].load(std::memory_order_relaxed);
218 for (
size_t i = 0; i < startSize; ++i) {
219 new (buf + i) T(defaultValue);
226 template <
typename InIterator>
235 template <
typename InIterator>
238 size_.store(startSize, std::memory_order_relaxed);
239 assert(std::distance(start,
end) ==
static_cast<difference_type
>(startSize));
259 : buffers_(std::move(other.buffers_)),
260 firstBucketShift_(other.firstBucketShift_),
261 firstBucketLen_(other.firstBucketLen_),
262 size_(other.size_.load(std::memory_order_relaxed)) {
263 other.size_.store(0, std::memory_order_relaxed);
266 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
267 other.buffers_[0].store(firstTwo, std::memory_order_relaxed);
268 other.buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_relaxed);
275 if (&other ==
this) {
281 size_.store(other.
size(), std::memory_order_relaxed);
292 if (&other ==
this) {
297 swap(firstBucketShift_, other.firstBucketShift_);
298 swap(firstBucketLen_, other.firstBucketLen_);
299 buffers_ = std::move(other.buffers_);
300 size_t curLen = size_.load(std::memory_order_relaxed);
301 size_.store(other.size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
302 other.size_.store(curLen, std::memory_order_relaxed);
313 void assign(size_type count,
const T& value) {
316 size_.store(count, std::memory_order_relaxed);
317 internalFillN(
begin(), count, value);
328 typename =
typename std::iterator_traits<It>::difference_type,
329 typename =
typename std::iterator_traits<It>::pointer,
330 typename =
typename std::iterator_traits<It>::reference,
331 typename =
typename std::iterator_traits<It>::value_type,
332 typename =
typename std::iterator_traits<It>::iterator_category>
335 auto count = std::distance(start,
end);
337 size_.store(count, std::memory_order_relaxed);
347 buffers_.allocAsNecessary({0, 0, firstBucketLen_},
capacity, bucketAndSubIndex(
capacity));
356 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
359 }
else if (curLen > len) {
361 auto newEnd =
begin() + len;
365 }
while (it != newEnd);
366 size_.store(len, std::memory_order_relaxed);
376 void resize(difference_type len,
const T& value) {
377 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
380 }
else if (curLen > len) {
382 auto newEnd =
begin() + len;
386 }
while (it != newEnd);
387 size_.store(len, std::memory_order_relaxed);
396 return 2 * firstBucketLen_;
404 size_t cap = 2 * firstBucketLen_;
405 for (
size_t b = 2; b < kMaxBuffers; ++b) {
406 if (!buffers_[b].load(std::memory_order_relaxed)) {
419 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
420 size_t len = binfo.bucketIndex;
421 size_t cap = binfo.bucketCapacity;
422 size_t b = binfo.bucket;
424 T* buf = buffers_[b].load(std::memory_order_relaxed);
434 size_.store(0, std::memory_order_release);
442 constexpr size_t kMaxExtra = 2;
443 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
446 size_t startBucket = std::max<size_t>(2, binfo.bucket + kMaxExtra);
448 for (
size_t b = startBucket; b < kMaxBuffers; ++b) {
449 T* ptr = buffers_[b].load(std::memory_order_relaxed);
453 if (buffers_.shouldDealloc(b)) {
456 buffers_[b].store(
nullptr, std::memory_order_release);
466 cv::dealloc<T>(buffers_[0].load(std::memory_order_acquire));
475 iterator
insert(const_iterator pos,
const T& value) {
476 auto it = insertPartial(pos);
487 iterator
insert(const_iterator pos, T&& value) {
488 auto it = insertPartial(pos);
489 new (&*it) T(std::move(value));
500 iterator
insert(const_iterator pos, size_type count,
const T& value) {
501 auto it = insertPartial(pos, count);
502 std::fill_n(it, count, value);
515 typename =
typename std::iterator_traits<InputIt>::difference_type,
516 typename =
typename std::iterator_traits<InputIt>::pointer,
517 typename =
typename std::iterator_traits<InputIt>::reference,
518 typename =
typename std::iterator_traits<InputIt>::value_type,
519 typename =
typename std::iterator_traits<InputIt>::iterator_category>
520 iterator
insert(const_iterator pos, InputIt first, InputIt last) {
521 size_t len = std::distance(first, last);
522 auto it = insertPartial(pos, len);
523 std::copy_n(first, len, it);
533 iterator
insert(const_iterator pos, std::initializer_list<T> ilist) {
534 return insert(pos, ilist.begin(), ilist.end());
543 iterator
erase(const_iterator pos) {
548 size_.fetch_sub(1, std::memory_order_relaxed);
557 return std::move(pos + 1, const_iterator(e), it);
568 iterator
erase(const_iterator first, const_iterator last) {
569 size_t len = std::distance(first, last);
571 size_t startIdx = first - it;
573 return it + (startIdx + len);
577 auto e_it = std::move(last,
cend(), it);
584 }
while (e_it != last);
586 size_.fetch_sub(len, std::memory_order_relaxed);
613 template <
typename... Args>
615 auto index = size_.fetch_add(1, std::memory_order_relaxed);
616 auto binfo = bucketAndSubIndex(index);
618 buffers_.allocAsNecessary(binfo);
620 iterator ret{
this, index, binfo};
622 if (Traits::kIteratorPreferSpeed) {
623 new (&*ret) T(std::forward<Args>(args)...);
625 new (buffers_[binfo.bucket] + binfo.bucketIndex) T(std::forward<Args>(args)...);
638 template <
typename Gen>
640 iterator ret = growByUninitialized(delta);
641 for (
auto it = ret; delta--; ++it) {
653 iterator
grow_by(size_type delta,
const T& t) {
654 iterator ret = growByUninitialized(delta);
655 internalFillN(ret, delta, t);
665 iterator ret = growByUninitialized(delta);
666 internalFillDefaultN(ret, delta);
678 typename =
typename std::iterator_traits<It>::difference_type,
679 typename =
typename std::iterator_traits<It>::pointer,
680 typename =
typename std::iterator_traits<It>::reference,
681 typename =
typename std::iterator_traits<It>::value_type,
682 typename =
typename std::iterator_traits<It>::iterator_category>
684 iterator ret = growByUninitialized(std::distance(start,
end));
685 internalInit(start,
end, ret);
694 iterator
grow_by(std::initializer_list<T> initList) {
695 return grow_by(std::begin(initList), std::end(initList));
705 size_t curSize = size_.load(std::memory_order_relaxed);
709 return {
this, n - 1, bucketAndSubIndex(n - 1)};
720 size_t curSize = size_.load(std::memory_order_relaxed);
722 return grow_by(n - curSize, t);
724 return {
this, n - 1, bucketAndSubIndex(n - 1)};
731 auto binfo = bucketAndSubIndex(size_.fetch_sub(1, std::memory_order_relaxed) - 1);
732 T* elt = buffers_[binfo.bucket].load(std::memory_order_relaxed) + binfo.bucketIndex;
744 const T& operator[](size_type index)
const {
745 auto binfo = bucketAndSubIndexForIndex(index);
746 T* buf = buffers_[binfo.bucket].load(std::memory_order_relaxed);
747 return buf[binfo.bucketIndex];
758 T& operator[](size_type index) {
759 auto binfo = bucketAndSubIndexForIndex(index);
760 T* buf = buffers_[binfo.bucket].load(std::memory_order_relaxed);
761 return buf[binfo.bucketIndex];
773 const T&
at(size_type index)
const {
774#if defined(__cpp_exceptions)
775 if (index >= size_.load(std::memory_order_relaxed)) {
776 throw std::out_of_range(
"Index too large");
779 return operator[](index);
791 T&
at(size_type index) {
792#if defined(__cpp_exceptions)
793 if (index >= size_.load(std::memory_order_relaxed)) {
794 throw std::out_of_range(
"Index too large");
797 return operator[](index);
808 return {
this, 0, {0, 0, firstBucketLen_}};
820 size_t curSize = size_.load(std::memory_order_relaxed);
821 auto binfo = bucketAndSubIndex(curSize);
822 return {
this, curSize, binfo};
833 return {
this, 0, {0, 0, firstBucketLen_}};
844 const_iterator
end()
const {
845 size_t curSize = size_.load(std::memory_order_relaxed);
846 auto binfo = bucketAndSubIndex(curSize);
847 return {
this, curSize, binfo};
858 return {
this, 0, {0, 0, firstBucketLen_}};
870 size_t curSize = size_.load(std::memory_order_relaxed);
871 auto binfo = bucketAndSubIndex(curSize);
872 return {
this, curSize, binfo};
884 return reverse_iterator(
end());
895 return reverse_iterator(
begin());
907 return const_reverse_iterator(
cend());
917 const_reverse_iterator
rend()
const {
918 return const_reverse_iterator(
cbegin());
927 return size_.load(std::memory_order_relaxed) == 0;
936 return Traits::kMaxVectorSize;
945 return size_.load(std::memory_order_relaxed);
953 return *buffers_[0].load(std::memory_order_relaxed);
961 return *buffers_[0].load(std::memory_order_relaxed);
988 swap(firstBucketShift_, oth.firstBucketShift_);
989 swap(firstBucketLen_, oth.firstBucketLen_);
990 size_t othlen = oth.size_.load(std::memory_order_relaxed);
991 oth.size_.store(size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
992 size_.store(othlen, std::memory_order_relaxed);
995 buffers_ = std::move(oth.buffers_);
999 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndexForIndex(
size_t index)
const {
1000#if defined(__clang__)
1001 if (index < firstBucketLen_) {
1002 return {0, index, firstBucketLen_};
1005 size_t l2idx = detail::log2(index);
1006 size_t bucket = (l2idx + 1) - firstBucketShift_;
1007 size_t bucketCapacity =
size_t{1} << l2idx;
1008 size_t bucketIndex = index - bucketCapacity;
1010 return {bucket, bucketIndex, bucketCapacity};
1012 return bucketAndSubIndex(index);
1016 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndex(
size_t index)
const {
1017 size_t l2idx = detail::log2(index | 1);
1018 size_t bucket = (l2idx + 1) - firstBucketShift_;
1019 size_t bucketCapacity =
size_t{1} << l2idx;
1020 size_t bucketIndex = index - bucketCapacity;
1022 bucket = index < firstBucketLen_ ? 0 : bucket;
1023 bucketIndex = index < firstBucketLen_ ? index : bucketIndex;
1024 bucketCapacity = index < firstBucketLen_ ? firstBucketLen_ : bucketCapacity;
1026 return {bucket, bucketIndex, bucketCapacity};
1029 template <
typename InIterator>
1030 void internalInit(InIterator start, InIterator
end, iterator it) {
1031 while (start !=
end) {
1032 new (&*it) T(*start);
1038 void internalFillN(iterator it,
size_t len,
const T& value) {
1039 for (; len--; ++it) {
1040 new (&*it) T(value);
1044 void internalFillDefaultN(iterator it,
size_t len) {
1045 for (; len--; ++it) {
1050 iterator growByUninitialized(size_type delta) {
1051 auto index = size_.fetch_add(delta, std::memory_order_relaxed);
1052 auto binfo = bucketAndSubIndex(index);
1053 buffers_.allocAsNecessary(binfo, delta, bucketAndSubIndex(index + delta));
1054 return {
this, index, binfo};
1057 iterator insertPartial(const_iterator pos) {
1059 auto index = size_.fetch_add(1, std::memory_order_relaxed);
1060 auto binfo = bucketAndSubIndex(index);
1061 buffers_.allocAsNecessary(binfo);
1063 return std::move_backward(pos, const_iterator(e), e + 1) - 1;
1066 iterator insertPartial(const_iterator pos,
size_t len) {
1068 auto index = size_.fetch_add(len, std::memory_order_relaxed);
1069 buffers_.allocAsNecessary(bucketAndSubIndex(index), len, bucketAndSubIndex(index + len));
1070 for (
auto it = e + len; it != e;) {
1074 return std::move_backward(pos, const_iterator(e), e + len) - len;
1079 SizeTraits::kDefaultCapacity / 2,
1080 SizeTraits::kMaxVectorSize,
1081 Traits::kPreferBuffersInline,
1082 Traits::kReallocStrategy> buffers_;
1083 static constexpr size_t kMaxBuffers =
decltype(buffers_)::kMaxBuffers;
1085 size_t firstBucketShift_;
1086 size_t firstBucketLen_;
1091 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, false>;
1092 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, true>;