相对通用的C语言队列

心血来潮加上上班摸鱼,写了个队列,感觉还是比较通用的吧,先看头文件:

#ifndef __QUEUE_H__
#define __QUEUE_H__

#include <stdint.h>

struct queue_handle_t
{
    //队列的名字
    char name[32];
    //创建内存地址的起始位置
    void *start_addr;
    //末尾地址
    void *finish_addr;
    //指向队首成员
    void *head_ptr;
    //指向队尾成员
    void *tail_ptr;
    //队列中最大成员数量
    uint32_t max_member;
    //队列中单个成员的尺寸
    uint32_t member_size;
    //当前成员数量
    uint32_t member_num;
    //是否被初始化
    uint16_t is_init;
    uint16_t is_creat;
    //内部用到的函数
    int (*internal_print)(const char *, ...);
    void *(*internal_malloc)(size_t);
    void (*internal_free)(void *);
};

/*
 * 初始化队列句柄
 * @param:
 *      handle:队列句柄
 * @note:
 *      在创建队列 creat_queue() 前调用
 * @return:
 *      0是成功
 */
int init_queue(struct queue_handle_t *handle,
               void *(*malloc_func)(size_t),
               void (*free_func)(void *),
               int (*log_func)(const char *format, ...));

/*
 * 创建队列
 * @param:
 *      handle:队列句柄
 *      name:队列的名字
 *      max_member:队列元素个数的最大数量
 *      size:每个元素的尺寸
 * @return:
 *      0是成功
 */
int creat_queue(struct queue_handle_t *handle, const char *name, const uint32_t max_member, const uint32_t size);

/*
 *删除队列
 *@param:
 *  handle:队列句柄
 */
int delete_queue(struct queue_handle_t *handle);

/*
 * 入队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 * @return:
 *      0是成功
 */
int entern_queue(struct queue_handle_t *handle, const void *data_ptr);
/*
 * 出队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 * @return:
 *      0是成功
 * @note:
 *      会删除队首元素
 */
int read_queue(struct queue_handle_t *handle, void *data_ptr);

/*
 * 出队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 * @return:
 *      0是成功
 * @note:
 *      不会删除队首元素
 */
int peek_queue(struct queue_handle_t *handle, void *data_ptr);

/*
 * 读取队尾的元素
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 * @return:
 *      0是成功
 * @note:
 */
int read_tail_queue(struct queue_handle_t *handle, void *data_ptr);

#endif

 

相信有的帅批看完头文件已经知道我是咋写的了,源文件:

//缺点:一个队列里的每个元素只能是大小一样的,在队列初始时就决定了队列的大小
#include "queue.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//提高这个值可以稍微提高一些安全性(避免空指针引用啥的)
#define QUEUE_SAFE_LEVEL 0

#define QUEUE_INIT_FLG 0XF1a5
#define QUEUE_CREAT_FLG 0XF1a5
#define QUEUE_LOG(fmt,arg...) if(handle->internal_print){handle->internal_print(fmt, ##arg);}

static inline int check_handle(struct queue_handle_t *handle)
{
#if QUEUE_SAFE_LEVEL >= 1
    if (handle == NULL)
    {
        return -1;
    }
    if (handle->is_init != QUEUE_INIT_FLG)
    {
        return -2;
    }
    if (handle->internal_malloc == NULL || handle->internal_free == NULL)
    {
        return -3;
    }
#endif
    return 0;
}


/*
 * 初始化队列句柄
 * @param:
 *      handle:队列句柄
 * @note:
 *      在创建队列时 creat_queue() 前调用
 * @return:
 *      0是成功
 */
int init_queue(struct queue_handle_t *handle,
               void *(*malloc_func)(size_t),
               void (*free_func)(void *),
               int (*log_func)(const char *format, ...))
{
    if (handle == NULL || malloc_func == NULL || free_func == NULL)
    {
        return -1;
    }
    memset(handle, 0, sizeof(struct queue_handle_t));
    handle->internal_malloc = malloc_func;
    handle->internal_free = free_func;
    handle->internal_print = log_func;
    handle->is_init = QUEUE_INIT_FLG;
    return 0;
}

/*
 * 创建队列
 * @param:
 *      handle:队列句柄
 *      name:队列的名字
 *      max_member:队列元素个数的最大数量
 *      size:每个元素的尺寸
 * @return:
 *      0是成功
 */
int creat_queue(struct queue_handle_t *handle, const char *name, const uint32_t max_member, const uint32_t size)
{
    void *p_start;
    uint32_t sum_size = max_member * size;
    if (check_handle(handle))
    {
        return -1;
    }
    //判断队列是否被创建
    if (handle->is_creat)
    {
        QUEUE_LOG("Warring:%s:%d:Queue %s May be Created Or Hnadle Not Init,New Queue Will Not be Created\n", __FUNCTION__, __LINE__, handle->name);
        return -1;
    }
    //队列名字是否合法
    if (strlen(name) <= 0 || strlen(name) >= 32)
    {
        QUEUE_LOG("Error:%s:%d:Queue Name Len Must More Than 0 But Less Than 32\n", __FUNCTION__, __LINE__, handle->name);
        return -1;
    }
    p_start = handle->internal_malloc(sum_size);
    if (p_start == NULL)
    {
        QUEUE_LOG("Error:%s:%d:Queue Creat Fail\n", __FUNCTION__, __LINE__);
        handle->start_addr = NULL;
        return -1;
    }
    handle->start_addr = p_start;
    handle->head_ptr = p_start;
    handle->tail_ptr = p_start;
    handle->max_member = max_member;
    handle->member_size = size;
    handle->member_num = 0;
    handle->finish_addr = (uint8_t *)p_start + sum_size;
    handle->is_creat = QUEUE_CREAT_FLG;
    strcpy(handle->name, name);
    memset(handle->start_addr, 0, sum_size);
    return 0;
}

/*
 *删除队列
 *@param:
 *  handle:队列句柄
 */
int delete_queue(struct queue_handle_t *handle)
{
    if (check_handle(handle) || handle->start_addr == NULL)
    {
        QUEUE_LOG("Error:%s:%d:Queue Delete Fail\n", __FUNCTION__, __LINE__);
        return -1;
    }
    handle->internal_free(handle->start_addr);
    memset(handle, 0, sizeof(struct queue_handle_t));
    handle->start_addr = NULL;
    handle->finish_addr = NULL;
    return 0;
}

/*
 * 入队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 *      size:加入元素的大小
 * @return:
 *      0是成功
 */
int entern_queue(struct queue_handle_t *handle, const void *data_ptr)
{
    if (check_handle(handle))
    {
        return -1;
    }
    //判断队列是否被创建
    if (handle->start_addr == NULL)
    {
        QUEUE_LOG("Error:%s:%d:Queue Enter Fail,Maybe Not Creat\n", __FUNCTION__, __LINE__);
        return -1;
    }
    //判断元素数量是否达到上限
    if (handle->member_num >= handle->max_member)
    {
        QUEUE_LOG("Error:%s:%d:Queue Enter Fail,Member Too Much\n", __FUNCTION__, __LINE__);
        return -1;
    }
    //如果队尾指针已经来到内存边界,那么将尾指针指回开头
    if (handle->tail_ptr >= handle->finish_addr)
    {
        handle->tail_ptr = handle->start_addr;
    }
    memcpy(handle->tail_ptr, data_ptr, handle->member_size);
    handle->tail_ptr = (uint8_t *)handle->tail_ptr + handle->member_size;
    handle->member_num++;
    return 0;
}

/*
 * 出队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 *      size:加入元素的大小
 * @return:
 *      0是成功
 * @note:
 *      会删除队首元素
 */
int read_queue(struct queue_handle_t *handle, void *data_ptr)
{
   if (check_handle(handle))
    {
        return -1;
    }
    //判断元素数量是否大于0
    if (handle->member_num <= 0)
    {
        QUEUE_LOG("Error:%s:%d:Queue Read Fail,Member Too Less\n", __FUNCTION__, __LINE__);
        return -1;
    }
    //如果队首指针已经来到内存边界,那么将首指针指回开头
    if (handle->head_ptr >= handle->finish_addr)
    {
        handle->head_ptr = handle->start_addr;
    }
    memcpy(data_ptr, handle->head_ptr, handle->member_size);
    handle->head_ptr = (uint8_t*)handle->head_ptr + handle->member_size;
    handle->member_num--;
    return 0;
}


/*
 * 出队
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 *      size:加入元素的大小
 * @return:
 *      0是成功
 * @note:
 *      不会删除队首元素
 */
int peek_queue(struct queue_handle_t *handle, void *data_ptr)
{
    if (check_handle(handle))
    {
        return -1;
    }
    //判断元素数量是否大于0
    if (handle->member_num <= 0)
    {
        QUEUE_LOG("Error:%s:%d:Queue Read Fail,Member Too Less\n", __FUNCTION__, __LINE__);
        return -1;
    }
    //如果队首指针已经来到内存边界,那么将首指针指回开头
    if (handle->head_ptr >= handle->finish_addr)
    {
        handle->head_ptr = handle->start_addr;
    }
    memcpy(data_ptr, handle->head_ptr, handle->member_size);
    return 0;
}

/*
 * 读取队尾的元素
 * @param:
 *      handle:队列句柄
 *      data_ptr:加入的元素
 *      size:加入元素的大小
 * @return:
 *      0是成功
 * @note:
 */
int read_tail_queue(struct queue_handle_t *handle, void *data_ptr)
{
    if (check_handle(handle))
    {
        return -1;
    }
    //判断元素数量是否大于0
    if (handle->member_num <= 0)
    {
        QUEUE_LOG("Error:%s:%d:Queue Read Fail,Member Too Less\n", __FUNCTION__, __LINE__);
        return -1;
    }
    //指向最后一个元素
    if (handle->tail_ptr <= handle->start_addr)
    {
        handle->tail_ptr = (uint8_t *)handle->finish_addr - handle->member_size;
    }
    else
    {
        handle->tail_ptr = (uint8_t*)handle->tail_ptr - handle->member_size;
    }
    memcpy(data_ptr, handle->tail_ptr, handle->member_size);
    handle->member_num--;
    return 0;
}


#if 0

struct a_t
{
    uint64_t v1;
    char v2;
    uint64_t v3;
} a ,aa;

int main()
{
    struct queue_handle_t h1;
    uint16_t arr[5] = {1, 2, 3};
    uint16_t read;
    double count = 100000;
    init_queue(&h1,malloc,free,printf);
    creat_queue(&h1, "test", 100, sizeof(a));

    printf("%ld\n", sizeof(struct a_t));

    for (double i = 0; i < count; i++)
    {
        a.v3 = i;
        entern_queue(&h1, &a);
        entern_queue(&h1, &a);
        entern_queue(&h1, &a);
        entern_queue(&h1, &a);
        read_queue(&h1, &aa);
        read_tail_queue(&h1, &aa);
        read_tail_queue(&h1, &aa);
        read_queue(&h1, &aa);
        printf("%.10f%%\r", 100 * (i / count));
        fflush(stdout);
    }
    printf("\n%d\n", aa.v3);
    return 0;
}

#endif


#undef QUEUE_INIT_FLG
#undef QUEUE_CREAT_FLG
#undef QUEUE_LOG

感觉单片机上也可以跑,什么,没有malloc?没事,用全局变量就可以了比如下面这样:

static char rnm_tq[100];

void *rnm_tq_malloc(size_t n)
{
    return &rnm_tq[0];
}

反正也是个静态队列。

哦,对了,如果涉及多线程的话,该还是得自己加锁的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值