Sword 内核队列二

#ifndef __GTC_FIFO_H_
#define __GTC_FIFO_H_

#ifndef GTC_MAX
#define GTC_MAX(a,b) ((a) > (b) ? (a) : (b))
#endif

#ifndef GTC_MIN
#define GTC_MIN(a,b) ((a) < (b) ? (a) : (b))
#endif

#ifdef __cplusplus
extern "C"
{
#endif

    struct gfifo {
        unsigned char *buffer;    /* the buffer holding the data */
        unsigned int size;    /* the size of the allocated buffer */
        unsigned int in;    /* data is added at offset (in % size) */
        unsigned int out;    /* data is extracted from off. (out % size) */
    };

    //队列初始化
    int gfifo_alloc(struct gfifo *fifo, unsigned int size);

    //压入队列
    unsigned int gfifo_put(struct gfifo *fifo, const unsigned char *buffer, unsigned int len);

    //弹出队列
    unsigned int gfifo_get(struct gfifo *fifo, unsigned char *buffer, unsigned int len);


#ifdef __cplusplus
}
#endif

#endif
#include "gfifo.h"

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

/********************************************************
   Func Name: gfifo_init
Date Created: 2019-4-1
 Description: 初始化
       Input: 
      Output: 
      Return: 
     Caution: 
*********************************************************/
static void gfifo_init(struct gfifo *fifo, void *buffer, unsigned int size)
{
    fifo->buffer = buffer;
    fifo->size = size;
    fifo->in = 0;
    fifo->out = 0;
}

/********************************************************
   Func Name: gfifo_roundup
Date Created: 2019-4-1
 Description: 扩展
       Input: 
      Output: 
      Return: size
     Caution: 
*********************************************************/
static unsigned int gfifo_roundup(unsigned int x)
{
    unsigned int i = 0;
    unsigned int y = 1;

    if (!x)
    {
        return 1;
    }

    for (i = x; i != 0; )
    {
        i >>= 1;
        y <<= 1;
    }

    return y;

}

/********************************************************
   Func Name: gfifo_alloc
Date Created: 2019-4-1
 Description: 内存分配
       Input: 
      Output: 
      Return: error code
     Caution: 
*********************************************************/
int gfifo_alloc(struct gfifo *fifo, unsigned int size)
{
    assert(fifo);

    unsigned char *buffer;

    /*
        size的值总是在调用者传进来的size参数的基础上向2的幂扩展,这是内核一贯的做法。
    这样的好处不言而喻--对kfifo->size取模运算可以转化为与运算,如下:
    fifo->in % fifo->size 可以转化为 fifo->in & (fifo->size – 1)
    在kfifo_alloc函数中,使用size & (size – 1)来判断size 是否为2幂,如果条件为真,则表示size不是2的幂,然后调用roundup_pow_of_two将之向上扩展为2的幂。
    */
    if (size & (size - 1)) 
    {
        size = gfifo_roundup(size);
    }

    buffer = calloc(1, size);
    if (NULL == buffer)
    {
        return -1;
    }

    gfifo_init(fifo, buffer, size);

    return 0;
}

/********************************************************
   Func Name: gfifo_put
Date Created: 2019-4-1
 Description: 压入队列
       Input: 
      Output: 
      Return: 压入队列数据长度
     Caution: 
*********************************************************/
unsigned int gfifo_put(struct gfifo *fifo, const unsigned char *buffer, unsigned int len)
{
    unsigned int left_over = 0;

    /*
    计算出实际写入队列数据大小
        (fifo->in - fifo->out)  已经使用空间大小
        fifo->size - (fifo->in - fifo->out)  可以使用空间大小
        len  需要写入数据大小
    */
    len = GTC_MIN(len, fifo->size - (fifo->in - fifo->out)); 

    /*
    计算出在队列in后面插入数据的大小
        fifo->in & (fifo->size - 1) 等同于 fifo->in % fifo->size
        fifo->size - (fifo->in & (fifo->size - 1))  表示in后面可写数据的长度
    */
    left_over = GTC_MIN(len, fifo->size - (fifo->in & (fifo->size - 1))); 

    //拷贝数据到in后面
    memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, left_over);

    //将剩余的数据拷贝到out前面
    memcpy(fifo->buffer, buffer + left_over, len - left_over);
    
    //更新in
    fifo->in += len;

    return len; 
}

/********************************************************
   Func Name: gfifo_get
Date Created: 2019-4-1
 Description: 弹出队列
       Input: 
      Output: 
      Return: 弹出队列
     Caution: 
*********************************************************/
unsigned int gfifo_get(struct gfifo *fifo, unsigned char *buffer, unsigned int len)
{
    assert(buffer);

    unsigned int readable_length = 0;

    /*
    计算出实际可读队列数据大小
        (fifo->in - fifo->out)  已经使用空间大小
    */

    len = GTC_MIN(len, fifo->in - fifo->out);

    /*
    计算出在队列out后面插入数据的大小
        fifo->in & (fifo->size - 1) 等同于 fifo->in % fifo->size
        fifo->size - (fifo->out & (fifo->size - 1))  表示out后面可读数据的长度
    */
    readable_length = GTC_MIN(len, fifo->size - (fifo->out & (fifo->size - 1))); 

    //拷贝数据
    memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), readable_length);

    //拷贝能从头部获取的数据
    memcpy(buffer + readable_length, fifo->buffer, len - readable_length);

    //更新out
    fifo->out += len;

    return len; 
}

猜你喜欢

转载自www.cnblogs.com/zhanggaofeng/p/10638829.html