MCPcopy Create free account
hub / github.com/danoon2/Boxedwine / dequeue_bulk

Function dequeue_bulk

source/util/concurrentqueue.h:2248–2338  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2246
2247 template<typename It>
2248 size_t dequeue_bulk(It& itemFirst, size_t max)
2249 {
2250 auto tail = this->tailIndex.load(std::memory_order_relaxed);
2251 auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);
2252 auto desiredCount = static_cast<size_t>(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit));
2253 if (details::circular_less_than<size_t>(0, desiredCount)) {
2254 desiredCount = desiredCount < max ? desiredCount : max;
2255 std::atomic_thread_fence(std::memory_order_acquire);
2256
2257 auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed);
2258
2259 tail = this->tailIndex.load(std::memory_order_acquire);
2260 auto actualCount = static_cast<size_t>(tail - (myDequeueCount - overcommit));
2261 if (details::circular_less_than<size_t>(0, actualCount)) {
2262 actualCount = desiredCount < actualCount ? desiredCount : actualCount;
2263 if (actualCount < desiredCount) {
2264 this->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release);
2265 }
2266
2267 // Get the first index. Note that since there's guaranteed to be at least actualCount elements, this
2268 // will never exceed tail.
2269 auto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel);
2270
2271 // Determine which block the first element is in
2272 auto localBlockIndex = blockIndex.load(std::memory_order_acquire);
2273 auto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire);
2274
2275 auto headBase = localBlockIndex->entries[localBlockIndexHead].base;
2276 auto firstBlockBaseIndex = firstIndex & ~static_cast<index_t>(BLOCK_SIZE - 1);
2277 auto offset = static_cast<size_t>(static_cast<typename std::make_signed<index_t>::type>(firstBlockBaseIndex - headBase) / static_cast<typename std::make_signed<index_t>::type>(BLOCK_SIZE));
2278 auto indexIndex = (localBlockIndexHead + offset) & (localBlockIndex->size - 1);
2279
2280 // Iterate the blocks and dequeue
2281 auto index = firstIndex;
2282 do {
2283 auto firstIndexInBlock = index;
2284 index_t endIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);
2285 endIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;
2286 auto block = localBlockIndex->entries[indexIndex].block;
2287 if (MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, details::deref_noexcept(itemFirst) = std::move((*(*block)[index])))) {
2288 while (index != endIndex) {
2289 auto& el = *((*block)[index]);
2290 *itemFirst++ = std::move(el);
2291 el.~T();
2292 ++index;
2293 }
2294 }
2295 else {
2296 MOODYCAMEL_TRY {
2297 while (index != endIndex) {
2298 auto& el = *((*block)[index]);
2299 *itemFirst = std::move(el);
2300 ++itemFirst;
2301 el.~T();
2302 ++index;
2303 }
2304 }
2305 MOODYCAMEL_CATCH (...) {

Callers

nothing calls this directly

Calls 5

deref_noexceptFunction · 0.85
loadMethod · 0.45
fetch_addMethod · 0.45
storeMethod · 0.45

Tested by

no test coverage detected