| 2470 | |
| 2471 | template<AllocationMode allocMode, typename U> |
| 2472 | inline bool enqueue(U&& element) |
| 2473 | { |
| 2474 | index_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed); |
| 2475 | index_t newTailIndex = 1 + currentTailIndex; |
| 2476 | if ((currentTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0) { |
| 2477 | // We reached the end of a block, start a new one |
| 2478 | auto head = this->headIndex.load(std::memory_order_relaxed); |
| 2479 | assert(!details::circular_less_than<index_t>(currentTailIndex, head)); |
| 2480 | if (!details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head))) { |
| 2481 | return false; |
| 2482 | } |
| 2483 | #ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX |
| 2484 | debug::DebugLock lock(mutex); |
| 2485 | #endif |
| 2486 | // Find out where we'll be inserting this block in the block index |
| 2487 | BlockIndexEntry* idxEntry; |
| 2488 | if (!insert_block_index_entry<allocMode>(idxEntry, currentTailIndex)) { |
| 2489 | return false; |
| 2490 | } |
| 2491 | |
| 2492 | // Get ahold of a new block |
| 2493 | auto newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>(); |
| 2494 | if (newBlock == nullptr) { |
| 2495 | rewind_block_index_tail(); |
| 2496 | idxEntry->value.store(nullptr, std::memory_order_relaxed); |
| 2497 | return false; |
| 2498 | } |
| 2499 | #ifdef MCDBGQ_TRACKMEM |
| 2500 | newBlock->owner = this; |
| 2501 | #endif |
| 2502 | newBlock->ConcurrentQueue::Block::template reset_empty<implicit_context>(); |
| 2503 | |
| 2504 | MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<U>(element)))) { |
| 2505 | // May throw, try to insert now before we publish the fact that we have this new block |
| 2506 | MOODYCAMEL_TRY { |
| 2507 | new ((*newBlock)[currentTailIndex]) T(std::forward<U>(element)); |
| 2508 | } |
| 2509 | MOODYCAMEL_CATCH (...) { |
| 2510 | rewind_block_index_tail(); |
| 2511 | idxEntry->value.store(nullptr, std::memory_order_relaxed); |
| 2512 | this->parent->add_block_to_free_list(newBlock); |
| 2513 | MOODYCAMEL_RETHROW; |
| 2514 | } |
| 2515 | } |
| 2516 | |
| 2517 | // Insert the new block into the index |
| 2518 | idxEntry->value.store(newBlock, std::memory_order_relaxed); |
| 2519 | |
| 2520 | this->tailBlock = newBlock; |
| 2521 | |
| 2522 | MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<U>(element)))) { |
| 2523 | this->tailIndex.store(newTailIndex, std::memory_order_release); |
| 2524 | return true; |
| 2525 | } |
| 2526 | } |
| 2527 | |
| 2528 | // Enqueue |
| 2529 | new ((*this->tailBlock)[currentTailIndex]) T(std::forward<U>(element)); |
nothing calls this directly
no test coverage detected