void allocAsNecessary()

in dispenso/detail/concurrent_vector_impl.h [381:447]


  void allocAsNecessary(const BucketInfo& binfo, ssize_t rangeLen, const BucketInfo& bend) {
    const size_t indexToCheck = (kStrategy == ConcurrentVectorReallocStrategy::kFullBufferAhead)
        ? 0
        : (kStrategy == ConcurrentVectorReallocStrategy::kHalfBufferAhead
               ? binfo.bucketCapacity / 2
               : binfo.bucketCapacity - 1);

    bool allocCurrentBucket =
        binfo.bucketIndex <= indexToCheck && binfo.bucketIndex + rangeLen > indexToCheck;
    if (DISPENSO_EXPECT(allocCurrentBucket || binfo.bucket < bend.bucket, 0)) {
      size_t sizeToAlloc = 0;

      size_t cap = binfo.bucketCapacity << ((bool)binfo.bucket + !allocCurrentBucket);
      size_t bucket = binfo.bucket + 1 + !allocCurrentBucket;
      for (; bucket <= bend.bucket; ++bucket, cap <<= 1) {
        if (!this->buffers_[bucket].load(std::memory_order_acquire)) {
          sizeToAlloc += cap;
        }
      }

      assert(bucket == bend.bucket + 1);
      assert((bucket == 1 && cap == bend.bucketCapacity) || cap == bend.bucketCapacity * 2);

      const size_t endToCheck = (kStrategy == ConcurrentVectorReallocStrategy::kFullBufferAhead)
          ? 0
          : (kStrategy == ConcurrentVectorReallocStrategy::kHalfBufferAhead
                 ? bend.bucketCapacity / 2
                 : bend.bucketCapacity - 1);

      if (DISPENSO_EXPECT(bend.bucketIndex > endToCheck, 0)) {
        if (!this->buffers_[bucket].load(std::memory_order_acquire)) {
          sizeToAlloc += cap;
        }
      }

      T* allocBufs = nullptr;
      if (sizeToAlloc) {
        allocBufs = cv::alloc<T>(sizeToAlloc);
      }
      bool firstAccounted = false;

      cap = binfo.bucketCapacity << ((bool)binfo.bucket + !allocCurrentBucket);
      bucket = binfo.bucket + 1 + !allocCurrentBucket;
      for (; bucket <= bend.bucket; ++bucket, cap <<= 1) {
        if (!this->buffers_[bucket].load(std::memory_order_acquire)) {
          this->buffers_[bucket].store(allocBufs, std::memory_order_release);
          allocBufs += cap;
          shouldDealloc_[bucket] = !firstAccounted;
          firstAccounted = true;
        }
      }

      assert(bucket == bend.bucket + 1);
      assert((bucket == 1 && cap == bend.bucketCapacity) || cap == bend.bucketCapacity * 2);

      if (DISPENSO_EXPECT(bend.bucketIndex > endToCheck, 0)) {
        if (!this->buffers_[bucket].load(std::memory_order_acquire)) {
          this->buffers_[bucket].store(allocBufs, std::memory_order_release);
          shouldDealloc_[bucket] = !firstAccounted;
        }
      }
    }
    for (size_t bucket = binfo.bucket; bucket <= bend.bucket; ++bucket) {
      while (DISPENSO_EXPECT(!this->buffers_[bucket].load(std::memory_order_acquire), 0)) {
      }
    }
  }