02 C语言使用队列实现缓存模块QueueBuffer
- Gitee源码仓库地址:C语言使用队列实现缓存模块QueueBuffer
jim@DESKTOP-SVP3BEM MINGW64 /d/1_git/many-repositories/27_队列缓存_系统缓存 (develop)
$ make
gcc -o demo queue_buffer_test.c queue_buffer_cfg.c queue_buffer.c queue.c
jim@DESKTOP-SVP3BEM MINGW64 /d/1_git/many-repositories/27_队列缓存_系统缓存 (develop)
$ ./demo.exe
got memory and write data 63 'U': UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
write data 15 'V': VVVVVVVVVVVVVVV, and send
receive and got 15 data : VVVVVVVVVVVVVVV
jim@DESKTOP-SVP3BEM MINGW64 /d/1_git/many-repositories/27_队列缓存_系统缓存 (develop)
default:
gcc -o demo queue_buffer_test.c queue_buffer_cfg.c queue_buffer.c queue.c
run:
./demo
clean:
rm demo
#include "queue_buffer_cfg.h"
#include "queue_buffer.h"
#include
#include
int main()
{
qbuf_t *ptmp, *psend, *prcv;
qbuf_groups_cfg();
ptmp = qbuf_alloc(QBUF_GROUP_TMPBUF);
if (!ptmp) {
printf("alloc memory error\n");
return -1;
}
memset(ptmp->addr, 'U', ptmp->size);
ptmp->addr[ptmp->size - 1] = '\0';
ptmp->len = ptmp->size;
printf("got memory and write data %d 'U': %s\n", ptmp->len - 1, ptmp->addr);
qbuf_free(ptmp);
psend = qbuf_alloc(QBUF_GROUP_DATBUF);
if (!psend) {
printf("alloc memory error\n");
return -1;
}
memset(psend->addr, 'V', psend->size);
psend->addr[psend->size - 1] = '\0';
psend->len = psend->size;
printf("write data %d 'V': %s, and send\n", psend->len - 1, psend->addr);
qbuf_put(psend);
prcv = qbuf_get(QBUF_GROUP_DATBUF);
if (!prcv) {
printf("get error\n");
return -1;
}
printf("receive and got %d data : %s\n", prcv->len - 1, prcv->addr);
return 0;
}
#ifndef _QUEUE_BUFFER_CONFIG_H_
#define _QUEUE_BUFFER_CONFIG_H_
#define DATBUF_MAX_BUF_CNT 4
#define DATBUF_MAX_BUF_LEN 16
extern char g_databuf_addr[DATBUF_MAX_BUF_CNT * DATBUF_MAX_BUF_LEN];
#define DATBUF_MAX_BUF_ADR g_databuf_addr
#define MSGBUF_MAX_BUF_CNT 8
#define MSGBUF_MAX_BUF_LEN 32
extern char g_msgbuf_addr[MSGBUF_MAX_BUF_CNT * MSGBUF_MAX_BUF_LEN];
#define MSGBUF_MAX_BUF_ADR g_msgbuf_addr
#define TMPBUF_MAX_BUF_CNT 16
#define TMPBUF_MAX_BUF_LEN 64
extern char g_tempbuf_addr[TMPBUF_MAX_BUF_CNT * TMPBUF_MAX_BUF_LEN];
#define TMPBUF_MAX_BUF_ADR g_tempbuf_addr
#define QBUF_MAX_COUNT (DATBUF_MAX_BUF_CNT + MSGBUF_MAX_BUF_CNT + TMPBUF_MAX_BUF_CNT)
extern void qbuf_groups_cfg(void);
#endif
#include "queue_buffer_cfg.h"
#include "queue_buffer.h"
char g_databuf_addr[DATBUF_MAX_BUF_CNT * DATBUF_MAX_BUF_LEN];
char g_msgbuf_addr[MSGBUF_MAX_BUF_CNT * MSGBUF_MAX_BUF_LEN];
char g_tempbuf_addr[TMPBUF_MAX_BUF_CNT * TMPBUF_MAX_BUF_LEN];
void qbuf_groups_cfg(void)
{
qbuf_group_cfg_t qg;
qbuf_init();
qg.type = QBUF_TYPE_ARRAY;
qg.addr = DATBUF_MAX_BUF_ADR;
qg.count = DATBUF_MAX_BUF_CNT;
qg.unitsize = DATBUF_MAX_BUF_LEN;
qbuf_group_cfg(&qg, QBUF_GROUP_DATBUF);
qg.type = QBUF_TYPE_ARRAY;
qg.addr = MSGBUF_MAX_BUF_ADR;
qg.count = MSGBUF_MAX_BUF_CNT;
qg.unitsize = MSGBUF_MAX_BUF_LEN;
qbuf_group_cfg(&qg, QBUF_GROUP_MSGBUF);
qg.type = QBUF_TYPE_ARRAY;
qg.addr = TMPBUF_MAX_BUF_ADR;
qg.count = TMPBUF_MAX_BUF_CNT;
qg.unitsize = TMPBUF_MAX_BUF_LEN;
qbuf_group_cfg(&qg, QBUF_GROUP_TMPBUF);
}
#ifndef _QUEUE_BUFFER_H_
#define _QUEUE_BUFFER_H_
#include "queue.h"
#include
#define QBUF_MARK 0xAABBCCDD
#define QBUF_ISVALID(x) ((x) && (x->mark == QBUF_MARK))
#define SYS_BUF_FLAG_MARK (0x000000FF)
#define SYS_BUF_FLAG_SOF (0x00000001)
#define SYS_BUF_FLAG_EOF (0x00000002)
enum {
QBUF_TYPE_MALLOC,
QBUF_TYPE_ARRAY
};
enum {
QBUF_GROUP_FREE,
QBUF_GROUP_DATBUF,
QBUF_GROUP_MSGBUF,
QBUF_GROUP_TMPBUF,
QBUF_GROUP_COUNT
};
typedef struct _qbuf_group_cfg {
uint32_t type;
uint32_t count;
uint32_t unitsize;
char *addr;
} qbuf_group_cfg_t;
typedef struct _qbuf {
queue_t queue;
uint32_t mark;
uint32_t flags;
uint32_t group;
char *addr;
uint32_t size;
uint32_t offset;
uint32_t len;
uint32_t id;
uint64_t user;
} qbuf_t;
extern void qbuf_init(void);
extern int qbuf_group_cfg(qbuf_group_cfg_t *qg, uint32_t group);
extern qbuf_t *qbuf_alloc(uint32_t group);
extern int qbuf_free(qbuf_t *buf);
extern int qbuf_put(qbuf_t *buf);
extern qbuf_t *qbuf_get(uint32_t group);
#endif
#include "queue_buffer.h"
#include "queue_buffer_cfg.h"
#include "util_errno.h"
#include
static queue_entry_t g_group_queue_entry[QBUF_GROUP_COUNT];
static qbuf_t g_qbuf[QBUF_MAX_COUNT + 1];
static int g_buf_id;
void qbuf_init(void)
{
int i;
qbuf_t *buf;
queue_t *pqueue;
g_buf_id = 0;
for (i = 0; i < QBUF_GROUP_COUNT; i++) {
queue_entry_init(&g_group_queue_entry[i]);
}
memset(g_qbuf, 0, sizeof(g_qbuf));
for (i = 0; i < QBUF_MAX_COUNT; i++) {
buf = &g_qbuf[i];
buf->mark = QBUF_MARK;
pqueue = &(buf->queue);
init_list_head(&(pqueue->node));
pqueue->queue_entry = &g_group_queue_entry[QBUF_GROUP_FREE];
queue_free(pqueue);
}
}
int qbuf_group_cfg(qbuf_group_cfg_t *qg, uint32_t queue_entry)
{
int i;
queue_entry_t *pqe;
qbuf_t *buf, *oldbuf;
queue_t *pqueue;
if (!qg || queue_entry <= QBUF_GROUP_FREE
|| queue_entry >= QBUF_GROUP_COUNT ) {
return -EPERM;
}
pqe = &(g_group_queue_entry[queue_entry]);
for (i = 0; i < QBUF_MAX_COUNT; i++) {
buf = &g_qbuf[i];
pqueue = &(buf->queue);
if (pqueue->queue_entry == pqe) {
pqueue->queue_entry = &g_group_queue_entry[QBUF_GROUP_FREE];
queue_free(pqueue);
}
}
queue_entry_destroy(pqe);
queue_entry_init(pqe);
oldbuf = NULL;
for (i = 0; i< qg->count; i++) {
pqueue = queue_alloc(&g_group_queue_entry[QBUF_GROUP_FREE]);
if (!pqueue) {
return -ENOMEM;
}
buf = container_of(pqueue, qbuf_t, queue);
buf->flags = 0;
buf->offset = 0;
buf->len = 0;
buf->size = qg->unitsize;
if (!oldbuf) {
buf->addr = qg->addr;
} else {
buf->addr = oldbuf->addr + qg->unitsize;
}
oldbuf = buf;
pqueue->queue_entry = pqe;
queue_free(pqueue);
}
return 0;
}
qbuf_t *qbuf_alloc(uint32_t group)
{
qbuf_t *buf;
queue_t *pqueue;
queue_entry_t *pqe;
if (group <= QBUF_GROUP_FREE
|| group >= QBUF_GROUP_COUNT ) {
return NULL;
}
pqe = &(g_group_queue_entry[group]);
pqueue = queue_alloc(pqe);
if (!pqueue) {
return NULL;
}
buf = container_of(pqueue, qbuf_t, queue);
buf->group = group;
buf->flags = 0;
buf->offset = 0;
buf->len = 0;
g_buf_id++;
if (g_buf_id == 0)
g_buf_id = 1;
buf->id = g_buf_id;
return buf;
}
int qbuf_free(qbuf_t *buf)
{
int res;
if (!QBUF_ISVALID(buf))
return -EPERM;
res = queue_free(&buf->queue);
if (res == 0) {
buf->group = QBUF_GROUP_FREE;
}
return res;
}
int qbuf_put(qbuf_t *buf)
{
int res;
if (!QBUF_ISVALID(buf))
return -EPERM;
res = queue_put(NULL, &(buf->queue), QUEUE_USED);
return res;
}
qbuf_t *qbuf_get(uint32_t group)
{
qbuf_t *buf;
queue_t *pqueue;
queue_entry_t *pqe;
if (group <= QBUF_GROUP_FREE
|| group >= QBUF_GROUP_COUNT ) {
return NULL;
}
pqe = &g_group_queue_entry[group];
pqueue = queue_get(pqe, QUEUE_USED);
if (!pqueue) {
return NULL;
}
buf = container_of(pqueue, qbuf_t, queue);
return buf;
}
#ifndef _QUEUE_H_
#define _QUEUE_H_
#include "list.h"
#include
#if 0
# include
typedef pthread_mutex_t queue_lock_t;
# define queue_lock_init(lock) pthread_mutex_init((lock), NULL)
# define queue_lock(lock) pthread_mutex_lock((lock))
# define queue_unlock(lock) pthread_mutex_unlock((lock))
# define queue_lock_destroy(lock) pthread_mutex_destroy((lock))
#else
typedef int queue_lock_t;
# define queue_lock_init(lock)
# define queue_lock(lock)
# define queue_unlock(lock)
# define queue_lock_destroy(lock)
#endif
enum {
QUEUE_USED,
QUEUE_FREE,
QUEUE_MEMBER_MAX
};
typedef struct _queue_entry {
struct list_head lists[QUEUE_MEMBER_MAX];
queue_lock_t lock;
} queue_entry_t;
typedef struct _queue {
struct list_head node;
queue_entry_t *queue_entry;
} queue_t;
extern void queue_entry_init(queue_entry_t *pqe);
#define queue_entry_destroy(pqe) queue_lock_destroy((pqe)->lock)
extern void queue_init(queue_t *pq);
extern int queue_put(queue_entry_t *pqe, queue_t *pq, int line);
extern queue_t *queue_get(queue_entry_t *pqe, int line);
#define queue_alloc(pqe) queue_get((pqe), QUEUE_FREE)
#define queue_free(pq) queue_put(NULL, (pq), QUEUE_FREE)
extern queue_t *queue_peek(queue_entry_t *pqe, int line);
extern int queue_count(queue_entry_t *pqe, int line);
#endif
#include "queue.h"
#include "util_errno.h"
void queue_entry_init(queue_entry_t *pqe)
{
if (!pqe)
return;
queue_lock_init(&(pqe->lock));
queue_lock(&(pqe->lock));
for (int i = 0; i < QUEUE_MEMBER_MAX; i++) {
init_list_head(&(pqe->lists[i]));
}
queue_unlock(&(pqe->lock));
}
void queue_init(queue_t *pq)
{
if (!pq)
return;
init_list_head(&(pq->node));
pq->queue_entry = NULL;
}
int queue_put(queue_entry_t *pqe, queue_t *pq, int line)
{
list_head_t *node, *head;
if (!pq || line >= QUEUE_MEMBER_MAX)
return -EPERM;
if (!pqe)
pqe = pq->queue_entry;
if (!pqe)
return -EPERM;
queue_lock(&(pqe->lock));
node = &(pq->node);
head = &(pqe->lists[line]);
list_del_init(node);
list_add_tail(node, head);
queue_unlock(&(pqe->lock));
return 0;
}
queue_t *queue_get(queue_entry_t *pqe, int line)
{
queue_t *pq;
list_head_t *node, *head;
if (!pqe || line >= QUEUE_MEMBER_MAX)
return NULL;
queue_lock(&(pqe->lock));
head = &(pqe->lists[line]);
pq = NULL;
if (!list_empty_careful(head)) {
pq = list_first_entry(head, queue_t, node);
node = &(pq->node);
list_del_init(node);
}
queue_unlock(&(pqe->lock));
return pq;
}
queue_t *queue_peek(queue_entry_t *pqe, int line)
{
queue_t *pq;
list_head_t *head;
if (!pqe || line >= QUEUE_MEMBER_MAX)
return NULL;
queue_lock(&(pqe->lock));
head = &(pqe->lists[line]);
pq = NULL;
if (!list_empty_careful(head)) {
pq = list_first_entry(head, queue_t, node);
}
queue_unlock(&(pqe->lock));
return pq;
}
int queue_count(queue_entry_t *pqe, int line)
{
int count = 0;
list_head_t *node, *n, *head;
if (!pqe || line >= QUEUE_MEMBER_MAX)
return -EPERM;
queue_lock(&(pqe->lock));
head = &(pqe->lists[line]);
if (!list_empty_careful(head)) {
list_for_each_safe(node, n, head) {
count++;
}
}
queue_unlock(&(pqe->lock));
return count;
}
#ifndef LIST_H
#define LIST_H
#include
typedef struct list_head {
struct list_head *next, *prev;
} list_head_t;
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
#undef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member);\
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
static inline void __list_add(struct list_head *_new,
struct list_head *prev,
struct list_head *next)
{
next->prev = _new;
_new->next = next;
_new->prev = prev;
prev->next = _new;
}
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
static inline void init_list_head(struct list_head *list)
{
list->next = list;
list->prev = list;
}
static inline void list_del_init(struct list_head *entry)
{
__list_del_entry(entry);
init_list_head(entry);
}
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
static inline void list_add_tail(struct list_head *_new, struct list_head *head)
{
__list_add(_new, head->prev, head);
}
#define LIST_POISON ((void *)0x0)
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = (struct list_head *)LIST_POISON;
entry->prev = (struct list_head *)LIST_POISON;
}
#endif
#ifndef _UTIL_ERRNO_H_
#define _UTIL_ERRNO_H_
#define EPERM 1
#define ENOENT 2
#define ESRCH 3
#define EINTR 4
#define EIO 5
#define ENXIO 6
#define E2BIG 7
#define ENOEXEC 8
#define EBADF 9
#define ECHILD 10
#define ENOMEM 12
#define EACCES 13
#define EFAULT 14
#define ENOTBLK 15
#define EBUSY 16
#define EEXIST 17
#define EXDEV 18
#define ENODEV 19
#define ENOTDIR 20
#define EISDIR 21
#define EINVAL 22
#define ENFILE 23
#define EMFILE 24
#define ENOTTY 25
#define ETXTBSY 26
#define EFBIG 27
#define ENOSPC 28
#define ESPIPE 29
#define EROFS 30
#define EMLINK 31
#define EPIPE 32
#define EDOM 33
#define ERANGE 34
#define EAGAIN 35
#define EWOULDBLOCK EAGAIN
#define EINPROGRESS 36
#define EALREADY 37
#define ENOTSOCK 38
#define EDESTADDRREQ 39
#define EMSGSIZE 40
#define EPROTOTYPE 41
#define ENOPROTOOPT 42
#define EPROTONOSUPPORT 43
#define ESOCKTNOSUPPORT 44
#define EOPNOTSUPP 45
#define EPFNOSUPPORT 46
#define EAFNOSUPPORT 47
#define EADDRINUSE 48
#define EADDRNOTAVAIL 49
#define ENETDOWN 50
#define ENETUNREACH 51
#define ENETRESET 52
#define ECONNABORTED 53
#define ECONNRESET 54
#define ENOBUFS 55
#define EISCONN 56
#define ENOTCONN 57
#define ESHUTDOWN 58
#define ETOOMANYREFS 59
#define ETIMEDOUT 60
#define ECONNREFUSED 61
#define ELOOP 62
#define ENAMETOOLONG 63
#define EHOSTDOWN 64
#define EHOSTUNREACH 65
#define ENOTEMPTY 66
#define EUSERS 68
#define EDQUOT 69
#define ESTALE 70
#define EREMOTE 71
#define ENOLCK 77
#define ENOSYS 78
#define ENOMSG 80
#define EIDRM 81
#define ENOSR 82
#define ETIME 83
#define EBADMSG 84
#define EPROTO 85
#define ENODATA 86
#define ENOSTR 87
#define ENOPKG 92
#define EILSEQ 116
#define ECHRNG 88
#define EL2NSYNC 89
#define EL3HLT 90
#define EL3RST 91
#define ELNRNG 93
#define EUNATCH 94
#define ENOCSI 95
#define EL2HLT 96
#define EBADE 97
#define EBADR 98
#define EXFULL 99
#define ENOANO 100
#define EBADRQC 101
#define EBADSLT 102
#define EDEADLK 11
#define EDEADLOCK EDEADLK
#define EBFONT 104
#define ENONET 105
#define ENOLINK 106
#define EADV 107
#define ESRMNT 108
#define ECOMM 109
#define EMULTIHOP 110
#define EDOTDOT 111
#define EOVERFLOW 112
#define ENOTUNIQ 113
#define EBADFD 114
#define EREMCHG 115
#define EUCLEAN 117
#define ENOTNAM 118
#define ENAVAIL 119
#define EISNAM 120
#define EREMOTEIO 121
#define ELIBACC 122
#define ELIBBAD 123
#define ELIBSCN 124
#define ELIBMAX 125
#define ELIBEXEC 126
#define ERESTART 127
#define ESTRPIPE 128
#define ENOMEDIUM 129
#define EMEDIUMTYPE 130
#define ECANCELED 131
#define ENOKEY 132
#define EKEYEXPIRED 133
#define EKEYREVOKED 134
#define EKEYREJECTED 135
#define EOWNERDEAD 136
#define ENOTRECOVERABLE 137
#define ERFKILL 138
#define EHWPOISON 139
#define ERESTARTSYS 512
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514
#define ENOIOCTLCMD 515
#define ERESTART_RESTARTBLOCK 516
#define EPROBE_DEFER 517
#define EOPENSTALE 518
#define ENOPARAM 519
#define EBADHANDLE 521
#define ENOTSYNC 522
#define EBADCOOKIE 523
#define ENOTSUPP 524
#define ETOOSMALL 525
#define ESERVERFAULT 526
#define EBADTYPE 527
#define EJUKEBOX 528
#define EIOCBQUEUED 529
#define ERECALLCONFLICT 530
#define ENOGRACE 531
#endif