MsgQueue.h
#ifndef __MSG_QUEUE_H__
#define __MSG_QUEUE_H__
/*****************************************************************************
* Define
*****************************************************************************/
#define MSGQ_DEBUG(...) printf(__VA_ARGS__);
//#define MSGQ_DEBUG(...)
/*****************************************************************************
* Typedef
*****************************************************************************/
typedef struct
{
int type;
void *data;
}Item;
typedef struct qnode
{
Item item;
struct qnode *prev;
struct qnode *next;
}QNode;
typedef struct
{
QNode *front;
QNode *rear;
int size;
pthread_mutex_t mutex;
}LinkQueue, MsgQueue;
/*****************************************************************************
* Extern Global Variable
*****************************************************************************/
/*****************************************************************************
* Extern Global Function
*****************************************************************************/
extern MsgQueue *CreateMsgQueue(void);
extern void DestoryMsgQueue(MsgQueue *pMsgQ);
extern int MsgQueueSend(MsgQueue *pMsgQ, int type, void *data, int len);
extern int MsgQueueRecv(MsgQueue *pMsgQ, int type, void *data, int len);
#endif /* __MSG_QUEUE_H__ */
MsgQueue.c
/*
* 双向链表实现的消息队列
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "msgqueue.h"
/*
* 初始化队列
*/
LinkQueue *CreateQueue(void)
{
LinkQueue *lq = NULL;
lq = (LinkQueue *)malloc(sizeof(LinkQueue));
if (lq != NULL)
{
lq->front = NULL;
lq->rear = NULL;
lq->size = 0;
pthread_mutex_init(&lq->mutex, NULL);
}
return lq;
}
/*
* 销毁队列
*/
void DestoryQueue(LinkQueue *lq)
{
QNode *pqnode = lq->front;
QNode *p;
pthread_mutex_lock(&lq->mutex);
while (pqnode != NULL)
{
p = pqnode->next;
free(pqnode);
pqnode = p;
}
free(lq);
pthread_mutex_unlock(&lq->mutex);
}
/*
* 判断是否为空
*/
static int QueueEmpty(LinkQueue *lq)
{
if (lq->rear == NULL && lq->front == NULL && lq->size == 0)
{
return 1;
}
else
{
return 0;
}
}
/*
* 入队
*/
int EnQueue(LinkQueue *lq, Item item)
{
QNode *pqnode;
pthread_mutex_lock(&lq->mutex);
pqnode = (QNode *)malloc(sizeof(QNode));
if (pqnode != NULL)
{
pqnode->item = item;
pqnode->prev = NULL;
pqnode->next = NULL;
if (lq->rear == NULL)
{
lq->front = pqnode;
lq->rear = pqnode;
}
else
{
lq->rear->next = pqnode;
pqnode->prev = lq->rear;
lq->rear = pqnode;
}
lq->size++;
pthread_mutex_unlock(&lq->mutex);
return 0;
}
pthread_mutex_unlock(&lq->mutex);
return -1;
}
/*
* 队首出列
*/
int DeQueue(LinkQueue *lq, Item *pitem)
{
QNode *pqnode;
pthread_mutex_lock(&lq->mutex);
if (QueueEmpty(lq) != 1)
{
pqnode = lq->front ;
lq->front = lq->front->next;
if (lq->front != NULL)
{
lq->front->prev = NULL;
}
*pitem = pqnode->item;
free(pqnode);
lq->size--;
pthread_mutex_unlock(&lq->mutex);
return 0;
}
pthread_mutex_unlock(&lq->mutex);
return -1;
}
/*
* 出队函数,找到type类型的消息,同一类型的消息先进先出
* type <= 0 队首出列
* type > 0 按类型出列消息,同一类弄型的消息先进先出
*
*/
int DeQueueByType(LinkQueue *lq, Item *pitem, int type)
{
QNode *pqnode;
pthread_mutex_lock(&lq->mutex);
if (QueueEmpty(lq) == 1)
{
pthread_mutex_unlock(&lq->mutex);
return -1;
}
pqnode = lq->front;
if (type > 0)
{
while (pqnode != NULL)
{
if (pqnode->item.type == type)
{
break;
}
pqnode = pqnode->next;
}
}
if (pqnode != NULL)
{
/* only one node */
if (lq->front == lq->rear)
{
lq->front = NULL;
lq->rear = NULL;
}
else
{
if (pqnode == lq->front)
{
lq->front = lq->front->next;
lq->front->prev = NULL;
}
else if (pqnode == lq->rear)
{
lq->rear = lq->rear->prev;
lq->rear->next = NULL;
}
else
{
pqnode->prev->next = pqnode->next;
pqnode->next->prev = pqnode->prev;
}
}
}
else
{
pthread_mutex_unlock(&lq->mutex);
return -1;
}
*pitem = pqnode->item;
free(pqnode);
lq->size--;
pthread_mutex_unlock(&lq->mutex);
return 0;
}
/* 队列长度 */
int QueueSize(LinkQueue *lq)
{
int size = 0;
pthread_mutex_lock(&lq->mutex);
size = lq->size;
pthread_mutex_unlock(&lq->mutex);
return size;
}
/* 遍历队列并对各数据项调用visit函数 */
void QueueTraverse(LinkQueue *lq, void (*visit)())
{
QNode *pqnode = lq->front;
pthread_mutex_lock(&lq->mutex);
while (pqnode != NULL)
{
visit(&pqnode->item);
pqnode = pqnode->next;
}
pthread_mutex_unlock(&lq->mutex);
}
MsgQueue *CreateMsgQueue(void)
{
return CreateQueue();
}
void DestoryMsgQueue(MsgQueue *pMsgQ)
{
DestoryQueue(pMsgQ);
}
int MsgQueueSend(MsgQueue *pMsgQ, int type, void *data, int len)
{
Item item;
if (type <= 0)
{
printf("%s: msg type can not be 0 or less than 0\r\n", __func__);
return -1;
}
item.data = malloc(len);
if (item.data == NULL)
{
printf("%s: malloc fail\r\n", __func__);
return -1;
}
memcpy(item.data, data, len);
item.type = type;
if (EnQueue(pMsgQ, item) != 0)
{
return -1;
}
return 0;
}
int MsgQueueRecv(MsgQueue *pMsgQ, int type, void *data, int len)
{
int ret;
Item item;
ret = DeQueueByType(pMsgQ, &item, type);
if (ret == 0)
{
memcpy(data, item.data, len);
free(item.data);
}
return ret;
}
测试代码 test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "msgqueue.h"
#define MAX_MSG 10
pthread_t send_tid;
pthread_t recv_tid;
void print(Item *item)
{
printf("type=%d, msg=%s\r\n", item->type, (char *)item->data);
}
#if 0
int main()
{
int i;
char buf[100];
MsgQueue *pMsgQ = CreateMsgQueue();
int type;
if (pMsgQ != NULL)
{
printf("send msg 0-9:\r\n");
for (i = 0; i < MAX_MSG; i++)
{
sprintf(buf, "msg %d", i);
printf("%s\r\n", buf);
if (MsgQueueSend(pMsgQ, i, buf, strlen(buf) + 1) < 0)
{
printf("MsgQueueSend fail\r\n");
}
}
QueueTraverse(pMsgQ, print);
printf("recv msg:\r\n");
for (i = 0; i < (MAX_MSG + 100); i++)
{
scanf("%d", &type);
if (MsgQueueRecv(pMsgQ, type, buf, sizeof(buf)) < 0)
{
printf("MsgQueueRecv msg type %d fail\r\n", type);
}
else
{
printf("%s\r\n", buf);
}
QueueTraverse(pMsgQ, print);
}
DestoryMsgQueue(pMsgQ);
printf("DestoryMsgQueue \r\n");
}
return 0;
}
#elif 1
/* 一个线程发,一个线程收 */
MsgQueue *pMsgQ;
void SendMsgThread(void)
{
unsigned int i = 0;
char buf[100];
while (1)
{
sprintf(buf, "msg %d", i);
printf("send %s\r\n", buf);
if (MsgQueueSend(pMsgQ, i, buf, strlen(buf) + 1) < 0)
{
printf("MsgQueueSend fail\r\n");
}
i++;
usleep(100000);
}
}
void RecvMsgThread(void)
{
unsigned int i = 0;
char buf[100];
sleep(10);
while (1)
{
if (MsgQueueRecv(pMsgQ, i, buf, sizeof(buf)) < 0)
{
printf("MsgQueueRecv fail\r\n");
}
else
{
printf("recv %s\r\n", buf);
}
usleep(10000);
}
}
int main()
{
int ret;
pMsgQ = CreateMsgQueue();
if (pMsgQ != NULL)
{
printf("Create msg queue succussful\r\n");
ret = pthread_create(&send_tid, NULL, (void *)SendMsgThread, NULL);
if (ret != 0)
{
printf("can not create SendMsgThread\r\n");
}
ret = pthread_create(&recv_tid, NULL, (void *)RecvMsgThread, NULL);
if (ret != 0)
{
printf("can not create RecvMsgThread\r\n");
}
while (1)
{
sleep(60);
}
}
return 0;
}
#endif