MCPcopy Create free account
hub / github.com/cameron314/concurrentqueue / dequeue_bulk

Function dequeue_bulk

concurrentqueue.h:2270–2360  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2268
2269 template<typename It>
2270 size_t dequeue_bulk(It& itemFirst, size_t max)
2271 {
2272 auto tail = this->tailIndex.load(std::memory_order_relaxed);
2273 auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);
2274 auto desiredCount = static_cast<size_t>(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit));
2275 if (details::circular_less_than<size_t>(0, desiredCount)) {
2276 desiredCount = desiredCount < max ? desiredCount : max;
2277 std::atomic_thread_fence(std::memory_order_acquire);
2278
2279 auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed);
2280
2281 tail = this->tailIndex.load(std::memory_order_acquire);
2282 auto actualCount = static_cast<size_t>(tail - (myDequeueCount - overcommit));
2283 if (details::circular_less_than<size_t>(0, actualCount)) {
2284 actualCount = desiredCount < actualCount ? desiredCount : actualCount;
2285 if (actualCount < desiredCount) {
2286 this->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release);
2287 }
2288
2289 // Get the first index. Note that since there's guaranteed to be at least actualCount elements, this
2290 // will never exceed tail.
2291 auto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel);
2292
2293 // Determine which block the first element is in
2294 auto localBlockIndex = blockIndex.load(std::memory_order_acquire);
2295 auto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire);
2296
2297 auto headBase = localBlockIndex->entries[localBlockIndexHead].base;
2298 auto firstBlockBaseIndex = firstIndex & ~static_cast<index_t>(BLOCK_SIZE - 1);
2299 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));
2300 auto indexIndex = (localBlockIndexHead + offset) & (localBlockIndex->size - 1);
2301
2302 // Iterate the blocks and dequeue
2303 auto index = firstIndex;
2304 do {
2305 auto firstIndexInBlock = index;
2306 index_t endIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);
2307 endIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;
2308 auto block = localBlockIndex->entries[indexIndex].block;
2309 if (MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, details::deref_noexcept(itemFirst) = std::move((*(*block)[index])))) {
2310 while (index != endIndex) {
2311 auto& el = *((*block)[index]);
2312 *itemFirst++ = std::move(el);
2313 el.~T();
2314 ++index;
2315 }
2316 }
2317 else {
2318 MOODYCAMEL_TRY {
2319 while (index != endIndex) {
2320 auto& el = *((*block)[index]);
2321 *itemFirst = std::move(el);
2322 ++itemFirst;
2323 el.~T();
2324 ++index;
2325 }
2326 }
2327 MOODYCAMEL_CATCH (...) {

Callers

nothing calls this directly

Calls 8

atomic_thread_fenceFunction · 0.85
deref_noexceptFunction · 0.85
moveFunction · 0.85
whileFunction · 0.85
loadMethod · 0.45
fetch_addMethod · 0.45
storeMethod · 0.45

Tested by

no test coverage detected