Inserts a new element at last segment of the queue
| 460 | |
| 461 | /// Inserts a new element at last segment of the queue |
| 462 | bool enqueue( value_type& val ) |
| 463 | { |
| 464 | // LSB is used as a flag in marked pointer |
| 465 | assert( (reinterpret_cast<uintptr_t>( &val ) & 1) == 0 ); |
| 466 | |
| 467 | typename gc::Guard segmentGuard; |
| 468 | segment * pTailSegment = m_SegmentList.tail( segmentGuard ); |
| 469 | if ( !pTailSegment ) { |
| 470 | // no segments, create the new one |
| 471 | pTailSegment = m_SegmentList.create_tail( pTailSegment, segmentGuard ); |
| 472 | assert( pTailSegment ); |
| 473 | } |
| 474 | |
| 475 | permutation_generator gen( quasi_factor()); |
| 476 | |
| 477 | // First, increment item counter. |
| 478 | // We sure that the item will be enqueued |
| 479 | // but if we increment the counter after inserting we can get a negative counter value |
| 480 | // if dequeuing occurs before incrementing (enqueue/dequeue race) |
| 481 | ++m_ItemCounter; |
| 482 | |
| 483 | while ( true ) { |
| 484 | CDS_DEBUG_ONLY( size_t nLoopCount = 0); |
| 485 | do { |
| 486 | typename permutation_generator::integer_type i = gen; |
| 487 | CDS_DEBUG_ONLY( ++nLoopCount ); |
| 488 | if ( pTailSegment->cells[i].data.load(memory_model::memory_order_relaxed).all()) { |
| 489 | // Cell is not empty, go next |
| 490 | m_Stat.onPushPopulated(); |
| 491 | } |
| 492 | else { |
| 493 | // Empty cell found, try to enqueue here |
| 494 | regular_cell nullCell; |
| 495 | if ( pTailSegment->cells[i].data.compare_exchange_strong( nullCell, regular_cell( &val ), |
| 496 | memory_model::memory_order_release, atomics::memory_order_relaxed )) |
| 497 | { |
| 498 | // Ok to push item |
| 499 | m_Stat.onPush(); |
| 500 | return true; |
| 501 | } |
| 502 | assert( nullCell.ptr()); |
| 503 | m_Stat.onPushContended(); |
| 504 | } |
| 505 | } while ( gen.next()); |
| 506 | |
| 507 | assert( nLoopCount == quasi_factor()); |
| 508 | |
| 509 | // No available position, create a new segment |
| 510 | pTailSegment = m_SegmentList.create_tail( pTailSegment, segmentGuard ); |
| 511 | |
| 512 | // Get new permutation |
| 513 | gen.reset(); |
| 514 | } |
| 515 | } |
| 516 | |
| 517 | /// Removes an element from first segment of the queue and returns it |
| 518 | /** |
nothing calls this directly
no test coverage detected