双链表实现的消息队列,可支持优先级读取

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值