@@ -67,8 +67,7 @@ class qu_mpsc_unbounded {
6767 static inline constexpr size_t BlockSizeMask = BlockSize - 1 ;
6868 static inline constexpr bool ConsumerCanSuspend = Config::ConsumerCanSuspend;
6969 static_assert (
70- BlockSize && ((BlockSize & (BlockSize - 1 )) == 0 ),
71- " BlockSize must be a power of 2"
70+ BlockSize && ((BlockSize & (BlockSize - 1 )) == 0 ), " BlockSize must be a power of 2"
7271 );
7372
7473 // Ensure that the subtraction of unsigned offsets always results in a value
@@ -102,16 +101,14 @@ class qu_mpsc_unbounded {
102101
103102 static constexpr size_t UNPADLEN =
104103 sizeof (std::atomic<void *>) + sizeof (tmc::detail::qu_storage<T>);
105- static constexpr size_t WANTLEN = (UNPADLEN + TMC_CACHE_LINE_SIZE - 1 ) &
106- static_cast <size_t >(
107- 0 - TMC_CACHE_LINE_SIZE
108- ); // round up to TMC_CACHE_LINE_SIZE
109- static constexpr size_t PADLEN =
110- UNPADLEN < WANTLEN ? (WANTLEN - UNPADLEN ) : 999 ;
104+ static constexpr size_t WANTLEN =
105+ (UNPADLEN + TMC_CACHE_LINE_SIZE - 1 ) &
106+ static_cast <size_t >(0 - TMC_CACHE_LINE_SIZE ); // round up to TMC_CACHE_LINE_SIZE
107+ static constexpr size_t PADLEN = UNPADLEN < WANTLEN ? (WANTLEN - UNPADLEN ) : 999 ;
111108
112109 struct empty {};
113- using Padding = std:: conditional_t <
114- Config::PackingLevel == 0 && PADLEN != 999 , char [PADLEN ], empty>;
110+ using Padding =
111+ std:: conditional_t < Config::PackingLevel == 0 && PADLEN != 999 , char [PADLEN ], empty>;
115112 TMC_NO_UNIQUE_ADDRESS Padding pad;
116113
117114 // Attempts to install Cons as a waiting consumer.
@@ -130,9 +127,8 @@ class qu_mpsc_unbounded {
130127 consumer_base* set_data_ready_or_get_waiting_consumer () noexcept
131128 requires(ConsumerCanSuspend)
132129 {
133- void * prev = flags.exchange (
134- reinterpret_cast <void *>(DATA_BIT ), std::memory_order_acq_rel
135- );
130+ void * prev =
131+ flags.exchange (reinterpret_cast <void *>(DATA_BIT ), std::memory_order_acq_rel);
136132 return static_cast <consumer_base*>(prev);
137133 }
138134
@@ -146,9 +142,8 @@ class qu_mpsc_unbounded {
146142 // waiting, its consumer_base pointer is returned so the caller can wake it.
147143 // Used only by close() to mark the cutoff slot.
148144 consumer_base* set_closed_or_get_waiting_consumer () noexcept {
149- void * prev = flags.exchange (
150- reinterpret_cast <void *>(CLOSED_BIT ), std::memory_order_acq_rel
151- );
145+ void * prev =
146+ flags.exchange (reinterpret_cast <void *>(CLOSED_BIT ), std::memory_order_acq_rel);
152147 if (reinterpret_cast <uintptr_t >(prev) < 4 ) {
153148 return nullptr ;
154149 }
@@ -160,11 +155,6 @@ class qu_mpsc_unbounded {
160155 return DATA_BIT == reinterpret_cast <uintptr_t >(f);
161156 }
162157
163- bool is_closed_sentinel () noexcept {
164- void * f = flags.load (std::memory_order_acquire);
165- return CLOSED_BIT == reinterpret_cast <uintptr_t >(f);
166- }
167-
168158 // Returns the raw flags value: DATA_BIT, CLOSED_BIT, or 0 (meaning empty).
169159 uintptr_t poll () noexcept {
170160 return reinterpret_cast <uintptr_t >(flags.load (std::memory_order_acquire));
@@ -218,8 +208,7 @@ class qu_mpsc_unbounded {
218208 char pad2[TMC_CACHE_LINE_SIZE - sizeof (void *)];
219209
220210 struct empty {};
221- using EmbeddedBlock =
222- std::conditional_t <Config::EmbedFirstBlock, data_block, empty>;
211+ using EmbeddedBlock = std::conditional_t <Config::EmbedFirstBlock, data_block, empty>;
223212 TMC_NO_UNIQUE_ADDRESS EmbeddedBlock embedded_block;
224213
225214public:
@@ -261,8 +250,8 @@ class qu_mpsc_unbounded {
261250 try_pull_zc_scope& operator =(const try_pull_zc_scope&) = delete ;
262251
263252 try_pull_zc_scope (try_pull_zc_scope&& Other) noexcept
264- : queue{Other.queue }, elem{Other.elem }, block{Other.block },
265- idx{Other. idx }, err{Other.err } {
253+ : queue{Other.queue }, elem{Other.elem }, block{Other.block }, idx{Other. idx },
254+ err{Other.err } {
266255 Other.elem = nullptr ;
267256 Other.err = tmc::qu_mpsc_unbounded_err::EMPTY ;
268257 }
@@ -335,15 +324,13 @@ class qu_mpsc_unbounded {
335324
336325 public:
337326 // / Constructs an empty scope. Evaluates to false when converted to bool.
338- pull_zc_scope () noexcept
339- : queue{nullptr }, elem{nullptr }, block{nullptr }, idx{0 } {}
327+ pull_zc_scope () noexcept : queue{nullptr }, elem{nullptr }, block{nullptr }, idx{0 } {}
340328
341329 pull_zc_scope (const pull_zc_scope&) = delete ;
342330 pull_zc_scope& operator =(const pull_zc_scope&) = delete ;
343331
344332 pull_zc_scope (pull_zc_scope&& Other) noexcept
345- : queue{Other.queue }, elem{Other.elem }, block{Other.block },
346- idx{Other.idx } {
333+ : queue{Other.queue }, elem{Other.elem }, block{Other.block }, idx{Other.idx } {
347334 Other.elem = nullptr ;
348335 }
349336
@@ -447,23 +434,19 @@ class qu_mpsc_unbounded {
447434 }
448435 // Actually unlink the blocks from the head of the queue.
449436 // They stay linked to each other.
450- unlinked[unlinkedCount - 1 ]->next .store (
451- nullptr , std::memory_order_release
452- );
437+ unlinked[unlinkedCount - 1 ]->next .store (nullptr , std::memory_order_release);
453438
454439 while (true ) {
455440 // Update their offsets to the end of the queue.
456- size_t boff =
457- tailBlock->offset .load (std::memory_order_relaxed) + BlockSize;
441+ size_t boff = tailBlock->offset .load (std::memory_order_relaxed) + BlockSize;
458442 for (size_t i = 0 ; i < unlinkedCount; ++i) {
459443 unlinked[i]->offset .store (boff, std::memory_order_relaxed);
460444 boff += BlockSize;
461445 }
462446
463447 // Re-link the tail of the queue to the head of the unlinked blocks.
464448 if (tailBlock->next .compare_exchange_strong (
465- next, unlinked[0 ], std::memory_order_acq_rel,
466- std::memory_order_acquire
449+ next, unlinked[0 ], std::memory_order_acq_rel, std::memory_order_acquire
467450 )) {
468451 break ;
469452 }
@@ -490,8 +473,7 @@ class qu_mpsc_unbounded {
490473 if (next == nullptr ) {
491474 data_block* newBlock = new data_block (offset + BlockSize);
492475 if (Block->next .compare_exchange_strong (
493- next, newBlock, std::memory_order_acq_rel,
494- std::memory_order_acquire
476+ next, newBlock, std::memory_order_acq_rel, std::memory_order_acquire
495477 )) {
496478 next = newBlock;
497479 } else {
@@ -512,18 +494,15 @@ class qu_mpsc_unbounded {
512494
513495 static inline bool block_before (data_block* A, data_block* B) noexcept {
514496 return circular_less_than (
515- A->offset .load (std::memory_order_relaxed),
516- B->offset .load (std::memory_order_relaxed)
497+ A->offset .load (std::memory_order_relaxed), B->offset .load (std::memory_order_relaxed)
517498 );
518499 }
519500
520- void advance_write_block_hint_at_least (
521- data_block* Current, data_block* Target
522- ) noexcept {
501+ void
502+ advance_write_block_hint_at_least (data_block* Current, data_block* Target) noexcept {
523503 while (block_before (Current, Target)) {
524504 if (write_block_hint.compare_exchange_weak (
525- Current, Target, std::memory_order_seq_cst,
526- std::memory_order_seq_cst
505+ Current, Target, std::memory_order_seq_cst, std::memory_order_seq_cst
527506 )) {
528507 return ;
529508 }
@@ -538,16 +517,12 @@ class qu_mpsc_unbounded {
538517
539518 data_block* get_mpsc_write_start_block (size_t Idx) noexcept {
540519 data_block* block = write_block_hint.load (std::memory_order_seq_cst);
541- if (!circular_less_than (
542- block->offset .load (std::memory_order_relaxed), 1 + Idx
543- )) {
520+ if (!circular_less_than (block->offset .load (std::memory_order_relaxed), 1 + Idx)) {
544521 // A later producer may have advanced the hint past this producer's
545522 // earlier reservation. Fall back to the consumer-managed reclaim
546523 // frontier, which cannot advance past an unproduced reservation.
547524 block = write_block.load (std::memory_order_seq_cst);
548- assert (circular_less_than (
549- block->offset .load (std::memory_order_relaxed), 1 + Idx
550- ));
525+ assert (circular_less_than (block->offset .load (std::memory_order_relaxed), 1 + Idx));
551526 }
552527 return block;
553528 }
@@ -626,18 +601,14 @@ class qu_mpsc_unbounded {
626601 while (!closed_ready.load (std::memory_order_acquire)) {
627602 TMC_CPU_PAUSE ();
628603 }
629- if (circular_less_than (
630- write_closed_at.load (std::memory_order_acquire), 1 + Idx
631- )) {
604+ if (circular_less_than (write_closed_at.load (std::memory_order_acquire), 1 + Idx)) {
632605 return nullptr ;
633606 }
634607 }
635608
636609 data_block* observed = get_mpsc_write_start_block (Idx);
637610
638- assert (circular_less_than (
639- observed->offset .load (std::memory_order_relaxed), 1 + Idx
640- ));
611+ assert (circular_less_than (observed->offset .load (std::memory_order_relaxed), 1 + Idx));
641612
642613 data_block* block = find_block (observed, Idx);
643614 advance_write_block_hint_at_least (observed, block);
@@ -649,9 +620,7 @@ class qu_mpsc_unbounded {
649620 Idx = read_offset;
650621 Block = read_block;
651622
652- assert (
653- circular_less_than (Block->offset .load (std::memory_order_relaxed), 1 + Idx)
654- );
623+ assert (circular_less_than (Block->offset .load (std::memory_order_relaxed), 1 + Idx));
655624
656625 Block = find_block (Block, Idx);
657626 return &Block->values [Idx & BlockSizeMask];
@@ -671,8 +640,7 @@ class qu_mpsc_unbounded {
671640 }
672641
673642 template <typename ... Args>
674- consumer_base*
675- write_element (element* Elem, Args&&... ConstructArgs) noexcept {
643+ consumer_base* write_element (element* Elem, Args&&... ConstructArgs) noexcept {
676644 Elem->data .emplace (static_cast <Args&&>(ConstructArgs)...);
677645 if constexpr (ConsumerCanSuspend) {
678646 return Elem->set_data_ready_or_get_waiting_consumer ();
@@ -697,9 +665,8 @@ class qu_mpsc_unbounded {
697665 // that case. Because close() takes a single fetch_add cutoff, a bulk
698666 // reservation cannot straddle the cutoff: it is either all pre-close or
699667 // all post-close in the seq_cst total order on write_offset.
700- data_block* get_write_ticket_bulk (
701- size_t Count, size_t & StartIdx, size_t & EndIdx
702- ) noexcept {
668+ data_block*
669+ get_write_ticket_bulk (size_t Count, size_t & StartIdx, size_t & EndIdx) noexcept {
703670 // seq_cst here serves the same purpose as in get_write_ticket: it orders
704671 // the reader's reclaim cutoff AND forms the producer side of the close
705672 // protocol (RMW-chain from close()'s release store to `closed`).
@@ -719,9 +686,9 @@ class qu_mpsc_unbounded {
719686
720687 data_block* observed = get_mpsc_write_start_block (StartIdx);
721688
722- assert (circular_less_than (
723- observed->offset .load (std::memory_order_relaxed), 1 + StartIdx
724- )) ;
689+ assert (
690+ circular_less_than ( observed->offset .load (std::memory_order_relaxed), 1 + StartIdx)
691+ );
725692
726693 // Ensure all blocks for the operation are allocated and available.
727694 data_block* startBlock = find_block (observed, StartIdx);
@@ -753,8 +720,7 @@ class qu_mpsc_unbounded {
753720 return false ;
754721 }
755722
756- consumer_base* cons =
757- write_element (elem, static_cast <Args&&>(ConstructArgs)...);
723+ consumer_base* cons = write_element (elem, static_cast <Args&&>(ConstructArgs)...);
758724 notify_consumer (cons);
759725 return true ;
760726 }
@@ -777,9 +743,7 @@ class qu_mpsc_unbounded {
777743 // Implementing handling for throwing construction is not possible with the
778744 // current design. This assert will also fire if no matching constructor can
779745 // be found for the iterator's dereferenced value.
780- static_assert (
781- std::is_nothrow_constructible_v<T, decltype (std::move (*Items))>
782- );
746+ static_assert (std::is_nothrow_constructible_v<T, decltype (std::move (*Items))>);
783747
784748 if (Count == 0 ) [[unlikely]] {
785749 return true ;
@@ -832,12 +796,8 @@ class qu_mpsc_unbounded {
832796 // Implementing handling for throwing construction is not possible with the
833797 // current design. This assert will also fire if no matching constructor can
834798 // be found for the iterator's dereferenced value.
835- static_assert (
836- std::is_nothrow_constructible_v<T, decltype (std::move (*Begin))>
837- );
838- return post_bulk (
839- static_cast <It&&>(Begin), static_cast <size_t >(End - Begin)
840- );
799+ static_assert (std::is_nothrow_constructible_v<T, decltype (std::move (*Begin))>);
800+ return post_bulk (static_cast <It&&>(Begin), static_cast <size_t >(End - Begin));
841801 }
842802
843803 // / Calculates the number of elements via
0 commit comments