On Sat, Mar 31, 2018 at 10:41 PM, Chris M. Thomasson
<cris...@charter.net> wrote:
> Notice how there is an acquire barrier inside of the CAS loop within the
> enqueue and dequeue functions of:
>
>
> http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
>
>
> ?
>
>
> Well, fwiw we can get rid of them by using stand alone fences:
>
>
> Btw, sorry for the membar abstraction. I can quickly get sick and tired of
> having to type out (std::memory_order_relaxed) all the damn time. ;^)
>
>
> Anyway, here is the simple code using Relacy:
>
> ___________________
>
> /* Membar Abstraction
>
> ___________________________________________________*/
>
> #define mbrlx std::memory_order_relaxed
>
> #define mbacq std::memory_order_acquire
>
> #define mbrel std::memory_order_release
>
> #define mb(mb_membar) std::atomic_thread_fence(mb_membar)
>
>
>
> template<typename T, unsigned int T_N>
>
> struct fifo
>
> {
>
>     struct cell
>
>     {
>
>         VAR_T(T) m_data;
>
>         std::atomic<unsigned int> m_ver;
>
>     };
>
>
>     std::atomic<unsigned int> m_head;
>
>     std::atomic<unsigned int> m_tail;
>
>     cell m_cells[T_N];
>
>
>     fifo() : m_head(0), m_tail(0)
>
>     {
>
>         for (unsigned int i = 0; i < T_N; ++i)
>
>         {
>
>             m_cells[i].m_ver.store(i, mbrlx);
>
>         }
>
>     }
>
>
>     bool push_try(T const& data)
>
>     {
>
>         cell* c = nullptr;
>
>         unsigned int ver = m_head.load(mbrlx);
>
>
>         do
>
>         {
>
>             c = &m_cells[ver & (T_N - 1)];
>
>             if (c->m_ver.load(mbrlx) != ver) return false;
>
>
>         } while (! m_head.compare_exchange_weak(ver, ver + 1, mbrlx));
>
>
>         mb(mbacq);
>
>         VAR(c->m_data) = data;
>
>         mb(mbrel);
>
>
>         c->m_ver.store(ver + 1, mbrlx);
>
>
>         return true;
>
>     }
>
>
>     bool pop_try(T& data)
>
>     {
>
>         cell* c = nullptr;
>
>         unsigned int ver = m_tail.load(mbrlx);
>
>
>         do
>
>         {
>
>             c = &m_cells[ver & (T_N - 1)];
>
>             if (c->m_ver.load(mbrlx) != ver + 1) return false;
>
>
>         } while (! m_tail.compare_exchange_weak(ver, ver + 1, mbrlx));
>
>
>         mb(mbacq);
>
>         data = VAR(c->m_data);
>
>         mb(mbrel);
>
>
>         c->m_ver.store(ver + T_N, mbrlx);
>
>
>         return true;
>
>     }
>
> };
>
> ___________________
>
>
>
> There is no need for any membars within the loops. The version count keeps
> everything in order.

compare_exchange in C/C++ has optional failure memory ordering, so the
following looks equivalent to me ;)

m_tail.compare_exchange_weak(ver, ver + 1, acquire, relaxed)

-- 

--- 
You received this message because you are subscribed to the Google Groups 
"Scalable Synchronization Algorithms" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to lock-free+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/lock-free/CAEeQi3sKGMzW9_okAH3%3Dzp6DDkvSoviE0JEe3LcrEy-7F9t7sw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to