QT实现基于QIODevice的线程安全环形队列

QT实现基于QIODevice的线程安全环形队列.

/******************************************************************************

    Copyright (C) 2017-2018 Zhang Fei <1158114251@qq.com>
    This class inherits the QIODevice class.
    This class implements a lock-free ring buffer (mainly for efficiency),
    noting that the lock-free condition is: a read thread, a write thread.
    If it is multiple read threads and multiple write threads,
    then you need two locks to lock the read and write threads.
    The buffer will signal when it is full.

******************************************************************************/
#ifndef QRING_BUFFER_H
#define QRING_BUFFER_H
#include <QtCore/qiodevice.h>
#include <QtCore/qbytearray.h>
#include <atomic>
#include <QDebug>
namespace QIO1
{
  class QRing_Buffer;
}

class  QRing_Buffer : public QIODevice
{
    Q_OBJECT

public:
     QRing_Buffer();
    ~QRing_Buffer();
     char * fifo_init(quint32 size);
     quint32 fifo_in(const char *buffer, quint32 size);
     quint32 fifo_out(char *buffer, quint32 size);
     qint64 size() const Q_DECL_OVERRIDE;
     qint64 pos() const Q_DECL_OVERRIDE;
     bool seek(qint64 off) Q_DECL_OVERRIDE;
     quint32 len;
signals:
        void fifo_full(void);
        void fifo_empty(void);
private slots:
        void fifo_full_deal(void);
        void fifo_empty_deal(void);

protected:
    qint64 writeData(const char *buffer, qint64 sizel) Q_DECL_OVERRIDE;
    qint64 readData(char *buffer, qint64 sizel) Q_DECL_OVERRIDE;

private:
    quint32 in;
    quint32 out;

    char * buffer;
};

#endif // QRING_BUFFER_H

实现:

 

# include "qring_buffer.h"
# include <QDebug>

# define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))

quint32 _min (quint32 a,quint32 b)
{
    return a < b ? a : b;
}

QRing_Buffer::QRing_Buffer()
{
    in  = 0;
    out = 0;
    len=0;
    buffer=NULL;

}

QRing_Buffer::~QRing_Buffer()
{
    if(buffer)
        free(buffer);
}


void QRing_Buffer::fifo_full_deal(void)
{

    qDebug()<<"fifo full";
}
void QRing_Buffer::fifo_empty_deal(void)
{
    qDebug()<<"fifo empty";
}

char * QRing_Buffer:: fifo_init(quint32 size)
{


    if (!is_power_of_2(size))
    {
        qDebug("size must be power of 2.\n");
        goto out;
    }

    if (buffer=(char *) malloc(size),!buffer)
    {
        qDebug("fail to malloc");
        goto out;
    }

    memset(buffer,0,size); // malloc lazy
    len=size;
    QObject::connect(this,&QRing_Buffer::fifo_full,\
                     this,&QRing_Buffer::fifo_full_deal);
    QObject::connect(this,&QRing_Buffer::fifo_empty,\
                     this,&QRing_Buffer::fifo_empty_deal);
    return buffer;
out:
    return NULL;
}

qint64 QRing_Buffer::size() const
{
    return in - out;
}

qint64 QRing_Buffer::pos() const
{
    return 0;
}

bool QRing_Buffer::seek(qint64 off)
{
     return false;
}


quint32 QRing_Buffer::fifo_in(const char *buffer, quint32 size)
{
    quint32 rsize;
    if (rsize=writeData(buffer, size),rsize!=size)
        emit fifo_full();
   return rsize;
}

quint32 QRing_Buffer::fifo_out(char *buffer, quint32 size)
{
    quint32 rsize;
    if (rsize =readData(buffer, size),rsize!=size)
        emit fifo_empty();
    return rsize;
}



qint64 QRing_Buffer::writeData(const char *buffer, qint64 sizel)
{
    quint32 l ;
    if(sizel<0)
    {
        return 0;
    }

    quint32 size =(quint32) sizel;

    size = _min(size, len - in + out);

    l = _min(size, len - (in & (len - 1)));

    memcpy(this->buffer + (in & (len - 1)), buffer, l);

    memcpy(this->buffer, buffer + l, size - l);
    /*
         The memory barrier only guarantees that the cpu is not out of order,
         and the index is updated after copying first.
    */
    std::atomic_thread_fence(std::memory_order_acquire);
    in += size;
    return size;
}

qint64 QRing_Buffer::readData(char *buffer, qint64 sizel)
{

    quint32 l ;
    if(sizel<0)
    {
        return 0;
    }
    quint32 size =(quint32) sizel;

    size= _min(size,in-out);

    l = _min(size, len - (out & (len - 1)));

    memcpy(buffer, this->buffer + (out & (len - 1)), l);

    memcpy(buffer + l, this->buffer, size - l);

    std::atomic_thread_fence(std::memory_order_acquire);

    out += size;
    return size;

}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值