@@ -391,27 +391,27 @@ class LockFreeSpscQueue
391391 */
392392 bool try_push (const T& item)
393393 {
394- if (m_items_pushed_count >= m_total_reserved_size) return false ;
395-
396- if (m_items_pushed_count < m_block1.size ()) {
397- m_block1[m_items_pushed_count] = item;
398- } else {
399- m_block2[m_items_pushed_count - m_block1.size ()] = item;
394+ if (m_items_pushed_count >= m_total_reserved_size) {
395+ return false ;
400396 }
397+
398+ // Construct a new object in its place by copying.
399+ *get_next_slot () = item;
400+
401401 m_items_pushed_count++;
402402 return true ;
403403 }
404404
405405 // Overload for movable types
406406 bool try_push (T&& item)
407407 {
408- if (m_items_pushed_count >= m_total_reserved_size) return false ;
409-
410- if (m_items_pushed_count < m_block1.size ()) {
411- m_block1[m_items_pushed_count] = std::move (item);
412- } else {
413- m_block2[m_items_pushed_count - m_block1.size ()] = std::move (item);
408+ if (m_items_pushed_count >= m_total_reserved_size) {
409+ return false ;
414410 }
411+
412+ // Construct a new object in its place by moving.
413+ *get_next_slot () = std::move (item);
414+
415415 m_items_pushed_count++;
416416 return true ;
417417 }
@@ -433,9 +433,12 @@ class LockFreeSpscQueue
433433 return false ;
434434 }
435435
436- T* slot_ptr = (m_items_pushed_count < m_block1.size ())
437- ? &m_block1[m_items_pushed_count]
438- : &m_block2[m_items_pushed_count - m_block1.size ()];
436+ T* slot_ptr = get_next_slot ();
437+
438+ // First, destroy the (potentially moved-from) object in the slot.
439+ if constexpr (!std::is_trivially_destructible_v<T>) {
440+ std::destroy_at (slot_ptr);
441+ }
439442
440443 // Construct the object directly in the queue's memory buffer.
441444 std::construct_at (slot_ptr, std::forward<Args>(args)...);
@@ -453,6 +456,7 @@ class LockFreeSpscQueue
453456 {
454457 if (m_owner_queue != nullptr ) {
455458 m_owner_queue->commit_write (m_items_pushed_count);
459+ m_owner_queue = nullptr ;
456460 }
457461 }
458462
@@ -476,6 +480,12 @@ class LockFreeSpscQueue
476480 , m_block1(b1), m_block2(b2)
477481 , m_total_reserved_size(b1.size() + b2.size()) {}
478482
483+ T* get_next_slot () {
484+ return (m_items_pushed_count < m_block1.size ())
485+ ? &m_block1[m_items_pushed_count]
486+ : &m_block2[m_items_pushed_count - m_block1.size ()];
487+ }
488+
479489 LockFreeSpscQueue* m_owner_queue = nullptr ;
480490 std::span<T> m_block1;
481491 std::span<T> m_block2;
0 commit comments