MCPcopy Create free account
hub / github.com/Snapchat/KeyDB / dequeue_bulk

Function dequeue_bulk

deps/concurrentqueue/concurrentqueue.h:2233–2323  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

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

Callers

nothing calls this directly

Calls 2

deref_noexceptFunction · 0.85

Tested by

no test coverage detected