环形队列

    队列在软件开发中被经常使用,该结构按照先进先出(FIFO)的原则处理数据元素。而本文介绍的环形队列是一种特殊的队列结构,它也是FIFO结构,但它是环形的,它把队列数据最后一个元素和第一个元素相连,形成一个环形,如下图所示:

 先给出几种环形队列的情况:

   1)FIFO空

    2)存放一些数据后

    3)读取一些数据

    4)存储数据长度达到缓存最大值时

实现源码:

#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>

//判断x是否是2的次方
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))

//取a和b中最小值
#define min(a, b) (((a) < (b)) ? (a) : (b))

typedef struct {
    int id;
    char name[64];
    int age;
}Student;

//环形队列结构
typedef struct 
{
    void         *buffer;    //缓冲区
    uint32_t     size;       //大小
    uint32_t     in;         //入口位置
    uint32_t     out;        //出口位置
    pthread_mutex_t *f_lock; //互斥锁
}Cyclic;

//初始化缓冲区
Cyclic* CyclicInit(void *buffer, uint32_t size, pthread_mutex_t *f_lock)
{
    assert(buffer);
    Cyclic *ring_buf = NULL;

    if (!is_power_of_2(size)) {
        fprintf(stderr,"size must be power of 2.\n");
        return ring_buf;
    }
    ring_buf = (Cyclic *)malloc(sizeof(Cyclic));
    if (!ring_buf) {
        fprintf(stderr,"Failed to malloc memory,errno:%u,reason:%s",errno, strerror(errno));
        return ring_buf;
    }
    memset(ring_buf, 0, sizeof(Cyclic));
    ring_buf->buffer = buffer;
    ring_buf->size = size;
    ring_buf->in = 0;
    ring_buf->out = 0;
    ring_buf->f_lock = f_lock;

    return ring_buf;
}

//释放缓冲区
void CyclicDestroy(Cyclic *ring_buf)
{
    if (ring_buf) {
        if (ring_buf->buffer) {
            free(ring_buf->buffer);
            ring_buf->buffer = NULL;
        }
        free(ring_buf);
        ring_buf = NULL;
    }
}

uint32_t __CyclicLen(const Cyclic *ring_buf)
{
    return (ring_buf->in - ring_buf->out);
}

uint32_t __CyclicGet(Cyclic *ring_buf, void * buffer, uint32_t size)
{
    assert(ring_buf || buffer);
    uint32_t len = 0;
    size  = min(size, ring_buf->in - ring_buf->out);        
    /* first get the data from fifo->out until the end of the buffer */
    len = min(size, ring_buf->size - (ring_buf->out & (ring_buf->size - 1)));
    memcpy(buffer, ring_buf->buffer + (ring_buf->out & (ring_buf->size - 1)), len);
    /* then get the rest (if any) from the beginning of the buffer */
    memcpy(buffer + len, ring_buf->buffer, size - len);
    ring_buf->out += size;
    return size;
}

uint32_t __CyclicPut(Cyclic *ring_buf, void *buffer, uint32_t size)
{
    assert(ring_buf || buffer);
    uint32_t len = 0;
    size = min(size, ring_buf->size - ring_buf->in + ring_buf->out);
    /* first put the data starting from fifo->in to buffer end */
    len  = min(size, ring_buf->size - (ring_buf->in & (ring_buf->size - 1)));
    memcpy(ring_buf->buffer + (ring_buf->in & (ring_buf->size - 1)), buffer, len);
    /* then put the rest (if any) at the beginning of the buffer */
    memcpy(ring_buf->buffer, buffer + len, size - len);
    ring_buf->in += size;

    return size;
}

//缓冲区的长度
uint32_t CyclicLen(const Cyclic *ring_buf)
{
    uint32_t len = 0;
    pthread_mutex_lock(ring_buf->f_lock);
    len = __CyclicLen(ring_buf);
    pthread_mutex_unlock(ring_buf->f_lock);
    return len;
}

//从缓冲区中取数据
uint32_t CyclicGet(Cyclic *ring_buf, void *buffer, uint32_t size)
{
    uint32_t ret;
    pthread_mutex_lock(ring_buf->f_lock);
    ret = __CyclicGet(ring_buf, buffer, size);
    //buffer中没有数据
    if (ring_buf->in == ring_buf->out)
          ring_buf->in = ring_buf->out = 0;
    pthread_mutex_unlock(ring_buf->f_lock);
    return ret;
}

//向缓冲区中存放数据
uint32_t CyclicPut(Cyclic *ring_buf, void *buffer, uint32_t size)
{
    uint32_t ret;
    pthread_mutex_lock(ring_buf->f_lock);
    ret = __CyclicPut(ring_buf, buffer, size);
    pthread_mutex_unlock(ring_buf->f_lock);
    return ret;
}

/*-----------------------------------------------------------------------------*/

#define BUFFER_SIZE  1024

void * consumer_proc(void *arg)
{
    Student info;
    Cyclic *ring_buf = (Cyclic *)arg;

    while (1) {
        sleep(2);
        printf("------------------------------------------\n");
        printf("get a student info from cyclic buffer.\n");
        CyclicGet(ring_buf, (void *)&info, sizeof(Student));
        printf("cyclic buffer length: %u\n", CyclicLen(ring_buf));
        printf("------------------------------------------\n");
    }
    return (void *)ring_buf;
}

void * producer_proc(void *arg)
{
    int i = 1;
    Cyclic *ring_buf = (Cyclic *)arg;
    Student info = {1,"zhangsan",20};

    while (1) {
        printf("******************************************\n"); 
        printf("put a student info to cyclic buffer.\n");
        info.id = ++i; 
        CyclicPut(ring_buf, (void *)&info, sizeof(Student));
        printf("cyclic buffer length: %u\n", CyclicLen(ring_buf));
        printf("******************************************\n");
        sleep(1);
    }
    return (void *)ring_buf;
}

 // 创建消费者线程
int consumer_thread(void *arg)
{
    int err;
    pthread_t tid;
    err = pthread_create(&tid, NULL, consumer_proc, arg);
    if (err != 0) {
        fprintf(stderr, "pthread_create failed !\n");
        exit(1);
    }
    return tid;
}

//创建生产者线程
int producer_thread(void *arg)  
{
    int err;
    pthread_t tid;
    err = pthread_create(&tid, NULL, producer_proc, arg);
    if (err != 0) {
        fprintf(stderr, "pthread_create failed !\n");
        exit(1);
    }
    return tid;
}

int main()
{
    pthread_mutex_t f_lock;
    Cyclic *ring_buf = NULL;
    char buffer[BUFFER_SIZE] = {0};

    ring_buf = CyclicInit(buffer, BUFFER_SIZE, &f_lock);
    if (NULL == ring_buf) {
        fprintf(stderr, "CyclicInit failed.\n");
        return -1;
    }

    producer_thread((void*)ring_buf);
    consumer_thread((void*)ring_buf);

    while (1)
        sleep(1);

    CyclicDestroy(ring_buf);

    return 0;
}

运行结果:

xzkj@xzkj:~/temp$ ./test 
******************************************
put a student info to cyclic buffer.
cyclic buffer length: 72
******************************************
******************************************
put a student info to cyclic buffer.
cyclic buffer length: 144
******************************************
------------------------------------------
get a student info from cyclic buffer.
cyclic buffer length: 72
------------------------------------------
******************************************
put a student info to cyclic buffer.
cyclic buffer length: 144
******************************************
******************************************
put a student info to cyclic buffer.
cyclic buffer length: 216
******************************************
------------------------------------------
get a student info from cyclic buffer.
cyclic buffer length: 144
------------------------------------------
******************************************
put a student info to cyclic buffer.
cyclic buffer length: 216
******************************************

                                                                           更多文章欢迎关注微信公众号~

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值