Boost logo

Boost :

Subject: Re: [boost] [lockfree::fifo] Review
From: Chris M. Thomasson (cristom_at_[hidden])
Date: 2009-12-18 05:48:28


"Tim Blechmann" <tim_at_[hidden]> wrote in message
news:4B23A083.7080008_at_klingt.org...

> >> i just went through the replies ... (maybe i should upcase some parts
> >> in
> >> the documentation, that the implementation focus on WORST CASE, not
> >> AVERAGE CASE performance ... people keep complaining that the
> >> stack/fifo
> >> may be outperformed be blocking algorithms, which is both true and
> >> irrelevant for me, as these implementations are soft real-time safe
> >> (and
> >> could be made hard real-time safe).
> >
> > Agreed.
> > Are you planning to augment your library with algorithms for different
> > needs? Like MPSC, SPMC and so forth? I think that could be useful,
> > because it looks like implementing the most generic MPMC case won't give
> > you the best results.

> i just added a lock-free single-producer/single-consumer ringbuffer to
> my git repository, branch topic/spsc_ringbuffer ... it implements an
> algorithm, that is commonly found in open source audio applications ...
> performs about 8 times faster than the m-s fifo queue (which is based on
> linked lists).

FWIW Tim, here is a very simple pseudo-code implementation of a nice
single-producer/consumer bounded queue:
_______________________________________________________________
template<template T,
                size_t T_depth>
class spsc_queue
{
    atomic<T*> m_buffer[T_depth]; // = { NULL }
    size_t m_head; // = 0
    size_t m_tail; // = 0

public:
    bool push(T* object)
    {
        if (m_buffer[m_head].load(memory_order_relaxed))
        {
            return false;
        }

        m_buffer[m_head].store(memory_order_release);

        ++m_head;

        if (m_head == T_depth)
        {
            m_head = 0;
        }

        return true;
    }

    T* pop()
    {
        T* object = m_buffer[m_tail].load(memory_order_acquire);

        if (object)
        {
            m_buffer[m_tail].store(NULL, memory_order_relaxed);

            ++m_tail;

            if (m_tail == T_depth)
            {
                m_tail = 0;
            }
        }

        return object;
    }
};
_______________________________________________________________

This is good because the producer and consumer do not interfere with each
other wrt the `spsc_queue::m_head/tail' variables. I think I noticed that
you are allowing producers and consumers to load both the reader and writer
variables and use them to determine boundary conditions (e.g., empty/full)
right?


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk