1、定义:
将消息封装成一个对象,发送端将其存储到一个缓冲区中,接收端从缓冲区中取消息。
2、结构图:
3、协作角色:
略
4、适用性:
1、发送端和接收端不能同步
2、要对发送对象进行优化,排序等特殊处理
5、实例:
1、需求,发送任务和接受任务不能同步,
2、实现:
msg_queue.h
#ifndef __MSG_QUEUE_H__
#define __MSG_QUEUE_H__
#define QUEUE_DATA_MAX_LEN 64
typedef struct qelem_s {
char *data[QUEUE_DATA_MAX_LEN];
struct qelem_s *next;
}qelem_t;
typedef struct queue_s {
qelem_t *first;
qelem_t *last;
unsigned int nelem;
unsigned int max;
pthread_mutex_t mutex;
}queue_t;
#define RET_SUCCESS 0
#define RET_FAIL (-1)
int msg_queue_init();
int msg_queue_create(unsigned int *qid);
int msg_queue_destroy(unsigned int qid);
int msg_queue_add(unsigned int qid, void *data, int size);
int msg_queue_del(unsigned int qid, void *data, int size);
int msg_queue_num(unsigned int qid, unsigned int *num);
#endif
msg_queue.c
#include
#include
#include
#include
#include "msg_queue.h"
#define QUEUE_MAX_NUM 3
#define QUEUE_MAX_LEN 16
struct msg_queue_s {
queue_t *queue[QUEUE_MAX_NUM];
int used[QUEUE_MAX_NUM];
pthread_mutex_t queue_lock;
};
struct msg_queue_s msg_queue;
int msg_queue_init()
{
memset((void *)&msg_queue, 0, sizeof(msg_queue));
pthread_mutex_init(&msg_queue.queue_lock, NULL);
return RET_SUCCESS;
}
int msg_queue_create(unsigned int *qid)
{
unsigned int i,j;
int ret;
qelem_t *new;
qelem_t *cur;
pthread_mutex_lock(&msg_queue.queue_lock);
for(i = 0; i < QUEUE_MAX_NUM; i++)
{
if(0 == msg_queue.used[i])
{
break;
}
}
if(i == QUEUE_MAX_NUM)
{
pthread_mutex_unlock(&msg_queue.queue_lock);
return RET_FAIL;
}
printf("%s %d\n",__func__, __LINE__);
msg_queue.queue[i] = (queue_t *)malloc(sizeof(queue_t));
if(!msg_queue.queue)
{
pthread_mutex_unlock(&msg_queue.queue_lock);
return RET_FAIL;
}
ret = pthread_mutex_init(&msg_queue.queue[i]->mutex, NULL);
if(ret != 0)
{
free(msg_queue.queue[i]);
pthread_mutex_unlock(&msg_queue.queue_lock);
return RET_FAIL;
}
msg_queue.queue[i]->first = (qelem_t *)malloc(sizeof(qelem_t));
if(!msg_queue.queue[i]->first)
{
free(msg_queue.queue[i]);
pthread_mutex_unlock(&msg_queue.queue_lock);
return RET_FAIL;
}
memset(msg_queue.queue[i]->first, 0, sizeof(qelem_t));
cur = msg_queue.queue[i]->last = msg_queue.queue[i]->first;
msg_queue.queue[i]->nelem = 0;
msg_queue.queue[i]->max = QUEUE_MAX_LEN - 2;
for(j = 0; j < QUEUE_MAX_LEN -2; j++)
{
new = (qelem_t *)malloc(sizeof(qelem_t));
if(!new)
{
while(msg_queue.queue[i]->first)
{
cur = msg_queue.queue[i]->first->next;
free(msg_queue.queue[i]->first);
msg_queue.queue[i]->first = cur;
}
free(msg_queue.queue[i]);
pthread_mutex_unlock(&msg_queue.queue_lock);
return RET_FAIL;
}
memset(new, 0, sizeof(qelem_t));
cur->next = new;
cur = new;
}
cur->next = msg_queue.queue[i]->first;
msg_queue.used[i] = 1;
*qid = i;
pthread_mutex_unlock(&msg_queue.queue_lock);
return RET_SUCCESS;
}
int msg_queue_destroy(unsigned int qid)
{
queue_t *queue;
qelem_t *cur;
if(qid >= QUEUE_MAX_NUM)
return RET_FAIL;
pthread_mutex_lock(&msg_queue.queue_lock);
queue = msg_queue.queue[qid];
while(msg_queue.queue[qid]->first)
{
cur = queue ->first->next;
free(queue ->first);
queue ->first = cur;
}
pthread_mutex_destroy(&queue->mutex);
free(queue);
pthread_mutex_unlock(&msg_queue.queue_lock);
return RET_SUCCESS;
}
int msg_queue_add(unsigned int qid, void *data, int size)
{
if(qid >= QUEUE_MAX_NUM)
return RET_FAIL;
//printf("enter into %s %s %d qid %d\n",__func__,(char *)data,size,qid);
queue_t *queue = msg_queue.queue[qid];
pthread_mutex_lock(&queue->mutex);
if(size > QUEUE_DATA_MAX_LEN)
size = QUEUE_DATA_MAX_LEN;
memcpy(queue->last->data, data,size);
queue->last = queue->last->next;
queue->nelem++;
if(queue->nelem > queue->max)
{
printf("this element cover the first one\n");
queue->nelem = queue->max;
}
pthread_mutex_unlock(&queue->mutex);
return RET_SUCCESS;
}
int msg_queue_del(unsigned int qid, void *data, int size)
{
if(qid >= QUEUE_MAX_NUM)
return RET_FAIL;
queue_t *queue = msg_queue.queue[qid];
pthread_mutex_lock(&queue->mutex);
if(queue->nelem <= 0)
{
pthread_mutex_unlock(&queue->mutex);
return RET_FAIL;
}
if(size > QUEUE_DATA_MAX_LEN)
size = QUEUE_DATA_MAX_LEN;
memcpy(data, queue->first->data, size);
memset(queue->first->data, 0, QUEUE_DATA_MAX_LEN);
queue->first = queue->first->next;
queue->nelem--;
pthread_mutex_unlock(&queue->mutex);
return RET_SUCCESS;
}
int msg_queue_num(unsigned int qid, unsigned int *num)
{
if(qid >= QUEUE_MAX_NUM)
return RET_FAIL;
*num = msg_queue.queue[qid]->nelem;
return RET_SUCCESS;
}
msg_send.h
#ifndef __MSG_SEND_H__
#define __MSG_SEND_H__
void* send_task(void *args);
#endif
msg_send.c
#include
#include
#include
#include "msg_send.h"
#include "msg_queue.h"
void* send_task(void *args)
{
int ret;
char buf[QUEUE_DATA_MAX_LEN];
unsigned int qid = *((int *)args);
int count = 0;
while(1)
{
//printf("input string and len < %d:\n",QUEUE_DATA_MAX_LEN);
memset(buf, 0 , sizeof(buf));
//scanf("%s",&buf);
sprintf(buf, "msg %d",count);
ret = msg_queue_add(qid, buf, strlen(buf));
count++;
sleep(1);
}
}
msg_receive.h
#ifndef __MSG_RECEIVE_H__
#define __MSG_RECEIVE_H__
void* receive_task(void *agrs);
#endif
msg_receive.c
#include
#include
#include
#include "msg_queue.h"
#include "msg_receive.h"
void* receive_task(void *args)
{
int ret;
char buf[QUEUE_DATA_MAX_LEN];
unsigned int qid = *((int *)args);
while(1)
{
memset(buf, 0 , sizeof(buf));
ret = msg_queue_del(qid, buf, QUEUE_DATA_MAX_LEN);
if(ret == RET_SUCCESS)
printf("msg is %s\n",buf);
sleep(3);
}
}
client.c
#include
#include
#include
#include
#include "msg_queue.h"
#include "msg_send.h"
#include "msg_receive.h"
int main()
{
pthread_t send, receive;
unsigned int qid;
int ret;
void *status;
msg_queue_init();
ret = msg_queue_create(&qid);
printf("qid is %d ret %d\n",qid,ret);
ret = pthread_create(&send, NULL, send_task, &qid);
if(ret != 0)
{
printf("create send task err\n");
return -1;
}
ret = pthread_create(&receive, NULL, receive_task, &qid);
if(ret != 0)
{
printf("create receive task err\n");
//pthread_destory(&send);
return -1;
}
pthread_join(send, &status);
pthread_join(receive, &status);
return 0;
}