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>;
192 detail::nextPow2(std::max(startCapacity, SizeTraits::kDefaultCapacity / 2)))),
193 firstBucketLen_(size_type{1} << firstBucketShift_) {
194 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
195 buffers_[0].store(firstTwo, std::memory_order_release);
196 buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_release);
203 size_.store(startSize, std::memory_order_relaxed);
204 T* buf = buffers_[0].load(std::memory_order_relaxed);
205 for (
size_t i = 0; i < startSize; ++i) {
215 size_.store(startSize, std::memory_order_relaxed);
216 T* buf = buffers_[0].load(std::memory_order_relaxed);
217 for (
size_t i = 0; i < startSize; ++i) {
218 new (buf + i) T(defaultValue);
225 template <
typename InIterator>
234 template <
typename InIterator>
237 size_.store(startSize, std::memory_order_relaxed);
238 assert(std::distance(start,
end) ==
static_cast<difference_type
>(startSize));
258 : buffers_(std::move(other.buffers_)),
259 firstBucketShift_(other.firstBucketShift_),
260 firstBucketLen_(other.firstBucketLen_),
261 size_(other.size_.load(std::memory_order_relaxed)) {
262 other.size_.store(0, std::memory_order_relaxed);
265 T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);
266 other.buffers_[0].store(firstTwo, std::memory_order_relaxed);
267 other.buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_relaxed);
274 if (&other ==
this) {
280 size_.store(other.
size(), std::memory_order_relaxed);
291 if (&other ==
this) {
296 swap(firstBucketShift_, other.firstBucketShift_);
297 swap(firstBucketLen_, other.firstBucketLen_);
298 buffers_ = std::move(other.buffers_);
299 size_t curLen = size_.load(std::memory_order_relaxed);
300 size_.store(other.size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
301 other.size_.store(curLen, std::memory_order_relaxed);
312 void assign(size_type count,
const T& value) {
315 size_.store(count, std::memory_order_relaxed);
316 internalFillN(
begin(), count, value);
327 typename =
typename std::iterator_traits<It>::difference_type,
328 typename =
typename std::iterator_traits<It>::pointer,
329 typename =
typename std::iterator_traits<It>::reference,
330 typename =
typename std::iterator_traits<It>::value_type,
331 typename =
typename std::iterator_traits<It>::iterator_category>
334 auto count = std::distance(start,
end);
336 size_.store(count, std::memory_order_relaxed);
346 buffers_.allocAsNecessary({0, 0, firstBucketLen_},
capacity, bucketAndSubIndex(
capacity));
355 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
358 }
else if (curLen > len) {
360 auto newEnd =
begin() + len;
364 }
while (it != newEnd);
365 size_.store(len, std::memory_order_relaxed);
375 void resize(difference_type len,
const T& value) {
376 difference_type curLen =
static_cast<difference_type
>(size_.load(std::memory_order_relaxed));
379 }
else if (curLen > len) {
381 auto newEnd =
begin() + len;
385 }
while (it != newEnd);
386 size_.store(len, std::memory_order_relaxed);
395 return 2 * firstBucketLen_;
403 size_t cap = 2 * firstBucketLen_;
404 for (
size_t b = 2; b < kMaxBuffers; ++b) {
405 if (!buffers_[b].load(std::memory_order_relaxed)) {
418 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
419 size_t len = binfo.bucketIndex;
420 size_t cap = binfo.bucketCapacity;
421 size_t b = binfo.bucket;
423 T* buf = buffers_[b].load(std::memory_order_relaxed);
433 size_.store(0, std::memory_order_release);
441 constexpr size_t kMaxExtra = 2;
442 auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));
445 size_t startBucket = std::max<size_t>(2, binfo.bucket + kMaxExtra);
447 for (
size_t b = startBucket; b < kMaxBuffers; ++b) {
448 T* ptr = buffers_[b].load(std::memory_order_relaxed);
452 if (buffers_.shouldDealloc(b)) {
455 buffers_[b].store(
nullptr, std::memory_order_release);
465 cv::dealloc<T>(buffers_[0].load(std::memory_order_acquire));
474 iterator
insert(const_iterator pos,
const T& value) {
475 auto it = insertPartial(pos);
486 iterator
insert(const_iterator pos, T&& value) {
487 auto it = insertPartial(pos);
488 new (&*it) T(std::move(value));
499 iterator
insert(const_iterator pos, size_type count,
const T& value) {
500 auto it = insertPartial(pos, count);
501 std::fill_n(it, count, value);
514 typename =
typename std::iterator_traits<InputIt>::difference_type,
515 typename =
typename std::iterator_traits<InputIt>::pointer,
516 typename =
typename std::iterator_traits<InputIt>::reference,
517 typename =
typename std::iterator_traits<InputIt>::value_type,
518 typename =
typename std::iterator_traits<InputIt>::iterator_category>
519 iterator
insert(const_iterator pos, InputIt first, InputIt last) {
520 size_t len = std::distance(first, last);
521 auto it = insertPartial(pos, len);
522 std::copy_n(first, len, it);
532 iterator
insert(const_iterator pos, std::initializer_list<T> ilist) {
533 return insert(pos, ilist.begin(), ilist.end());
542 iterator
erase(const_iterator pos) {
547 size_.fetch_sub(1, std::memory_order_relaxed);
556 return std::move(pos + 1, const_iterator(e), it);
567 iterator
erase(const_iterator first, const_iterator last) {
568 size_t len = std::distance(first, last);
570 size_t startIdx = first - it;
572 return it + (startIdx + len);
576 auto e_it = std::move(last,
cend(), it);
583 }
while (e_it != last);
585 size_.fetch_sub(len, std::memory_order_relaxed);
612 template <
typename... Args>
614 auto index = size_.fetch_add(1, std::memory_order_relaxed);
615 auto binfo = bucketAndSubIndex(index);
617 buffers_.allocAsNecessary(binfo);
619 iterator ret{
this, index, binfo};
621 if (Traits::kIteratorPreferSpeed) {
622 new (&*ret) T(std::forward<Args>(args)...);
624 new (buffers_[binfo.bucket] + binfo.bucketIndex) T(std::forward<Args>(args)...);
637 template <
typename Gen>
639 iterator ret = growByUninitialized(delta);
640 for (
auto it = ret; delta--; ++it) {
652 iterator
grow_by(size_type delta,
const T& t) {
653 iterator ret = growByUninitialized(delta);
654 internalFillN(ret, delta, t);
664 iterator ret = growByUninitialized(delta);
665 internalFillDefaultN(ret, delta);
677 typename =
typename std::iterator_traits<It>::difference_type,
678 typename =
typename std::iterator_traits<It>::pointer,
679 typename =
typename std::iterator_traits<It>::reference,
680 typename =
typename std::iterator_traits<It>::value_type,
681 typename =
typename std::iterator_traits<It>::iterator_category>
683 iterator ret = growByUninitialized(std::distance(start,
end));
684 internalInit(start,
end, ret);
693 iterator
grow_by(std::initializer_list<T> initList) {
694 return grow_by(std::begin(initList), std::end(initList));
704 size_t curSize = size_.load(std::memory_order_relaxed);
708 return {
this, n - 1, bucketAndSubIndex(n - 1)};
719 size_t curSize = size_.load(std::memory_order_relaxed);
721 return grow_by(n - curSize, t);
723 return {
this, n - 1, bucketAndSubIndex(n - 1)};
730 auto binfo = bucketAndSubIndex(size_.fetch_sub(1, std::memory_order_relaxed) - 1);
731 T* elt = buffers_[binfo.bucket].load(std::memory_order_relaxed) + binfo.bucketIndex;
744 auto binfo = bucketAndSubIndexForIndex(index);
745 T* buf = buffers_[binfo.bucket].load(std::memory_order_relaxed);
746 return buf[binfo.bucketIndex];
758 auto binfo = bucketAndSubIndexForIndex(index);
759 T* buf = buffers_[binfo.bucket].load(std::memory_order_relaxed);
760 return buf[binfo.bucketIndex];
772 const T&
at(size_type index)
const {
773#if defined(__cpp_exceptions)
774 if (index >= size_.load(std::memory_order_relaxed)) {
775 throw std::out_of_range(
"Index too large");
790 T&
at(size_type index) {
791#if defined(__cpp_exceptions)
792 if (index >= size_.load(std::memory_order_relaxed)) {
793 throw std::out_of_range(
"Index too large");
807 return {
this, 0, {0, 0, firstBucketLen_}};
819 size_t curSize = size_.load(std::memory_order_relaxed);
820 auto binfo = bucketAndSubIndex(curSize);
821 return {
this, curSize, binfo};
832 return {
this, 0, {0, 0, firstBucketLen_}};
843 const_iterator
end()
const {
844 size_t curSize = size_.load(std::memory_order_relaxed);
845 auto binfo = bucketAndSubIndex(curSize);
846 return {
this, curSize, binfo};
857 return {
this, 0, {0, 0, firstBucketLen_}};
869 size_t curSize = size_.load(std::memory_order_relaxed);
870 auto binfo = bucketAndSubIndex(curSize);
871 return {
this, curSize, binfo};
883 return reverse_iterator(
end());
894 return reverse_iterator(
begin());
906 return const_reverse_iterator(
cend());
916 const_reverse_iterator
rend()
const {
917 return const_reverse_iterator(
cbegin());
926 return size_.load(std::memory_order_relaxed) == 0;
935 return Traits::kMaxVectorSize;
944 return size_.load(std::memory_order_relaxed);
952 return *buffers_[0].load(std::memory_order_relaxed);
960 return *buffers_[0].load(std::memory_order_relaxed);
987 swap(firstBucketShift_, oth.firstBucketShift_);
988 swap(firstBucketLen_, oth.firstBucketLen_);
989 size_t othlen = oth.size_.load(std::memory_order_relaxed);
990 oth.size_.store(size_.load(std::memory_order_relaxed), std::memory_order_relaxed);
991 size_.store(othlen, std::memory_order_relaxed);
994 buffers_ = std::move(oth.buffers_);
998 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndexForIndex(
size_t index)
const {
999#if defined(__clang__)
1000 if (index < firstBucketLen_) {
1001 return {0, index, firstBucketLen_};
1004 size_t l2idx = detail::log2(index);
1005 size_t bucket = (l2idx + 1) - firstBucketShift_;
1006 size_t bucketCapacity =
size_t{1} << l2idx;
1007 size_t bucketIndex = index - bucketCapacity;
1009 return {bucket, bucketIndex, bucketCapacity};
1011 return bucketAndSubIndex(index);
1015 DISPENSO_INLINE cv::BucketInfo bucketAndSubIndex(
size_t index)
const {
1016 size_t l2idx = detail::log2(index | 1);
1017 size_t bucket = (l2idx + 1) - firstBucketShift_;
1018 size_t bucketCapacity =
size_t{1} << l2idx;
1019 size_t bucketIndex = index - bucketCapacity;
1021 bucket = index < firstBucketLen_ ? 0 : bucket;
1022 bucketIndex = index < firstBucketLen_ ? index : bucketIndex;
1023 bucketCapacity = index < firstBucketLen_ ? firstBucketLen_ : bucketCapacity;
1025 return {bucket, bucketIndex, bucketCapacity};
1028 template <
typename InIterator>
1029 void internalInit(InIterator start, InIterator
end, iterator it) {
1030 while (start !=
end) {
1031 new (&*it) T(*start);
1037 void internalFillN(iterator it,
size_t len,
const T& value) {
1038 for (; len--; ++it) {
1039 new (&*it) T(value);
1043 void internalFillDefaultN(iterator it,
size_t len) {
1044 for (; len--; ++it) {
1049 iterator growByUninitialized(size_type delta) {
1050 auto index = size_.fetch_add(delta, std::memory_order_relaxed);
1051 auto binfo = bucketAndSubIndex(index);
1052 buffers_.allocAsNecessary(binfo, delta, bucketAndSubIndex(index + delta));
1053 return {
this, index, binfo};
1056 iterator insertPartial(const_iterator pos) {
1058 auto index = size_.fetch_add(1, std::memory_order_relaxed);
1059 auto binfo = bucketAndSubIndex(index);
1060 buffers_.allocAsNecessary(binfo);
1062 return std::move_backward(pos, const_iterator(e), e + 1) - 1;
1065 iterator insertPartial(const_iterator pos,
size_t len) {
1067 auto index = size_.fetch_add(len, std::memory_order_relaxed);
1068 buffers_.allocAsNecessary(bucketAndSubIndex(index), len, bucketAndSubIndex(index + len));
1069 for (
auto it = e + len; it != e;) {
1073 return std::move_backward(pos, const_iterator(e), e + len) - len;
1076 alignas(kCacheLineSize) cv::ConVecBuffer<
1078 SizeTraits::kDefaultCapacity / 2,
1079 SizeTraits::kMaxVectorSize,
1080 Traits::kPreferBuffersInline,
1081 Traits::kReallocStrategy> buffers_;
1082 static constexpr size_t kMaxBuffers =
decltype(buffers_)::kMaxBuffers;
1084 size_t firstBucketShift_;
1085 size_t firstBucketLen_;
1087 alignas(kCacheLineSize) std::atomic<size_t> size_{0};
1090 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, false>;
1091 friend class cv::ConcurrentVectorIterator<
ConcurrentVector<T, Traits>, T, true>;