@@ -58,13 +58,14 @@ struct prod_cons_impl<wr<relat::single, relat::single, trans::unicast>> {
5858 return false ;
5959 }
6060
61- template <typename W, typename F, typename E>
62- bool pop (W* /* wrapper*/ , circ::u2_t & /* cur*/ , F&& f, E* elems) {
61+ template <typename W, typename F, typename R, typename E>
62+ bool pop (W* /* wrapper*/ , circ::u2_t & /* cur*/ , F&& f, R&& out, E* elems) {
6363 auto cur_rd = circ::index_of (rd_.load (std::memory_order_relaxed));
6464 if (cur_rd == circ::index_of (wt_.load (std::memory_order_acquire))) {
6565 return false ; // empty
6666 }
6767 std::forward<F>(f)(&(elems[cur_rd].data_ ));
68+ std::forward<R>(out)(true );
6869 rd_.fetch_add (1 , std::memory_order_release);
6970 return true ;
7071 }
@@ -80,8 +81,9 @@ struct prod_cons_impl<wr<relat::single, relat::multi , trans::unicast>>
8081 return false ;
8182 }
8283
83- template <typename W, typename F, template <std::size_t , std::size_t > class E , std::size_t DS, std::size_t AS>
84- bool pop (W* /* wrapper*/ , circ::u2_t & /* cur*/ , F&& f, E<DS, AS>* elems) {
84+ template <typename W, typename F, typename R,
85+ template <std::size_t , std::size_t > class E , std::size_t DS, std::size_t AS>
86+ bool pop (W* /* wrapper*/ , circ::u2_t & /* cur*/ , F&& f, R&& out, E<DS, AS>* elems) {
8587 byte_t buff[DS];
8688 for (unsigned k = 0 ;;) {
8789 auto cur_rd = rd_.load (std::memory_order_relaxed);
@@ -92,6 +94,7 @@ struct prod_cons_impl<wr<relat::single, relat::multi , trans::unicast>>
9294 std::memcpy (buff, &(elems[circ::index_of (cur_rd)].data_ ), sizeof (buff));
9395 if (rd_.compare_exchange_weak (cur_rd, cur_rd + 1 , std::memory_order_release)) {
9496 std::forward<F>(f)(buff);
97+ std::forward<R>(out)(true );
9598 return true ;
9699 }
97100 ipc::yield (k);
@@ -156,8 +159,9 @@ struct prod_cons_impl<wr<relat::multi , relat::multi, trans::unicast>>
156159 return false ;
157160 }
158161
159- template <typename W, typename F, template <std::size_t , std::size_t > class E , std::size_t DS, std::size_t AS>
160- bool pop (W* /* wrapper*/ , circ::u2_t & /* cur*/ , F&& f, E<DS, AS>* elems) {
162+ template <typename W, typename F, typename R,
163+ template <std::size_t , std::size_t > class E , std::size_t DS, std::size_t AS>
164+ bool pop (W* /* wrapper*/ , circ::u2_t & /* cur*/ , F&& f, R&& out, E<DS, AS>* elems) {
161165 byte_t buff[DS];
162166 for (unsigned k = 0 ;;) {
163167 auto cur_rd = rd_.load (std::memory_order_relaxed);
@@ -179,6 +183,7 @@ struct prod_cons_impl<wr<relat::multi , relat::multi, trans::unicast>>
179183 std::memcpy (buff, &(elems[circ::index_of (cur_rd)].data_ ), sizeof (buff));
180184 if (rd_.compare_exchange_weak (cur_rd, cur_rd + 1 , std::memory_order_release)) {
181185 std::forward<F>(f)(buff);
186+ std::forward<R>(out)(true );
182187 return true ;
183188 }
184189 ipc::yield (k);
@@ -263,20 +268,20 @@ struct prod_cons_impl<wr<relat::single, relat::multi, trans::broadcast>> {
263268 return true ;
264269 }
265270
266- template <typename W, typename F, typename E>
267- bool pop (W* wrapper, circ::u2_t & cur, F&& f, E* elems) {
271+ template <typename W, typename F, typename R, typename E>
272+ bool pop (W* wrapper, circ::u2_t & cur, F&& f, R&& out, E* elems) {
268273 if (cur == cursor ()) return false ; // acquire
269274 auto * el = elems + circ::index_of (cur++);
270275 std::forward<F>(f)(&(el->data_ ));
271276 for (unsigned k = 0 ;;) {
272277 auto cur_rc = el->rc_ .load (std::memory_order_acquire);
273- circ:: cc_t rem_cc = cur_rc & ep_mask;
274- if (rem_cc == 0 ) {
278+ if (( cur_rc & ep_mask) == 0 ) {
279+ std::forward<R>(out)( true );
275280 return true ;
276281 }
277- if (el-> rc_ . compare_exchange_weak (cur_rc,
278- cur_rc & ~ static_cast < rc_t >(wrapper-> connected_id ()),
279- std::memory_order_release)) {
282+ auto nxt_rc = cur_rc & ~ static_cast < rc_t >(wrapper-> connected_id ());
283+ if (el-> rc_ . compare_exchange_weak (cur_rc, nxt_rc, std::memory_order_release)) {
284+ std::forward<R>(out)((nxt_rc & ep_mask) == 0 );
280285 return true ;
281286 }
282287 ipc::yield (k);
@@ -395,8 +400,8 @@ struct prod_cons_impl<wr<relat::multi, relat::multi, trans::broadcast>> {
395400 return true ;
396401 }
397402
398- template <typename W, typename F, typename E, std::size_t N>
399- bool pop (W* wrapper, circ::u2_t & cur, F&& f, E(& elems)[N]) {
403+ template <typename W, typename F, typename R, typename E, std::size_t N>
404+ bool pop (W* wrapper, circ::u2_t & cur, F&& f, R&& out, E(& elems)[N]) {
400405 auto * el = elems + circ::index_of (cur);
401406 auto cur_fl = el->f_ct_ .load (std::memory_order_acquire);
402407 if (cur_fl != ~static_cast <flag_t >(cur)) {
@@ -406,17 +411,18 @@ struct prod_cons_impl<wr<relat::multi, relat::multi, trans::broadcast>> {
406411 std::forward<F>(f)(&(el->data_ ));
407412 for (unsigned k = 0 ;;) {
408413 auto cur_rc = el->rc_ .load (std::memory_order_acquire);
409- circ:: cc_t rem_cc = cur_rc & rc_mask;
410- if (rem_cc == 0 ) {
414+ if (( cur_rc & rc_mask) == 0 ) {
415+ std::forward<R>(out)( true );
411416 el->f_ct_ .store (cur + N - 1 , std::memory_order_release);
412417 return true ;
413418 }
414- if ((rem_cc & ~wrapper->connected_id ()) == 0 ) {
419+ auto nxt_rc = inc_rc (cur_rc) & ~static_cast <rc_t >(wrapper->connected_id ());
420+ bool last_one = false ;
421+ if ((last_one = (nxt_rc & rc_mask) == 0 )) {
415422 el->f_ct_ .store (cur + N - 1 , std::memory_order_release);
416423 }
417- if (el->rc_ .compare_exchange_weak (cur_rc,
418- inc_rc (cur_rc) & ~static_cast <rc_t >(wrapper->connected_id ()),
419- std::memory_order_release)) {
424+ if (el->rc_ .compare_exchange_weak (cur_rc, nxt_rc, std::memory_order_release)) {
425+ std::forward<R>(out)(last_one);
420426 return true ;
421427 }
422428 ipc::yield (k);
0 commit comments