buffer(缓冲区模式)

1、定义:

        将消息封装成一个对象,发送端将其存储到一个缓冲区中,接收端从缓冲区中取消息。

2、结构图:

          buffer(缓冲区模式)_第1张图片

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;
}


 

 

 

 

 

 

 

 

你可能感兴趣的:(设计模式)