消息队列的实现

消息队列的实现转换为经典的生产者——消费者模型。

 

网上很多实现只能在生产者:消费 = 1:1的情况下运行。

本实现参考《Unix 网络编程——卷二 进程间通信》,可以在任意配比下运行。

还参考了《一种同步消息队列模型(C++)》,但由于 STL中的deque不必担心内存分配问题,所以实现只有互斥相关的操作。

 

来看基础消息的定义,作为基类——有其它消息类型可以模拟C++中的继承机制。

typedef struct ares_msg_block
{
pthread_t pid;
void *msg;
}msg_block_t;

共享内存区域,即循环消息队列的结构定义

typedef struct ares_msg_box
{
pthread_cond_t not_full;
pthread_cond_t not_empty;
pthread_mutex_t mutex;
//消息的循环队列
size_t first;
size_t last;
size_t size;
size_t nready; ///多少个消息,判断满与空
msg_block_t * msg_array[0]; ///柔性数组
}msg_box_t;


消息邮箱的初始化。

View Code
///初始化
static void msgbox_init(msg_box_t *mbox,size_t size)
{
assert(mbox);
pthread_mutex_init(&(mbox->mutex),NULL);
pthread_cond_init(&(mbox->not_full),NULL);
pthread_cond_init(&(mbox->not_empty),NULL);
mbox->size = size;
mbox->nready= 0;
mbox->first = 0;
mbox->last = 0;
memset(mbox->msg_array,sizeof(void *)*size,0);
}
msg_box_t * msgbox_new(size_t size)
{
msg_box_t *mbox = (msg_box_t *)malloc(sizeof(msg_box_t)+sizeof(void *)*size);
if(mbox)
msgbox_init(mbox,size);
return mbox;
}


消息邮箱的释放。

View Code
void msgbox_free(msg_box_t *mbox)
{
///等待所有的信号量结束
pthread_mutex_lock(&(mbox->mutex));

pthread_cond_destroy(&(mbox->not_full));
pthread_cond_destroy(&(mbox->not_empty));
pthread_mutex_unlock(&(mbox->mutex));
pthread_mutex_destroy(&(mbox->mutex));
free(mbox);
}



发送消息

View Code
/**
@note 等待一个事件的到来
*/
void msgbox_post(msg_box_t *mbox,msg_block_t *msg)
{
int wakeup = 0;
pthread_mutex_lock(&(mbox->mutex));
///等待到有存放的空间
while(mbox->nready == mbox->size )
pthread_cond_wait(&(mbox->not_full),&(mbox->mutex));

mbox->msg_array[mbox->last] = msg;
mbox->last = (mbox->last+1)%mbox->size;
if(0==mbox->nready)
wakeup = 1;
mbox->nready++;
pthread_mutex_unlock(&(mbox->mutex));
if(wakeup)
pthread_cond_signal(&(mbox->not_empty));
}

取消息

View Code
/**
@note 等待一个事件的到来
*/
void msgbox_fetch(msg_box_t *mbox,msg_block_t **pmsg)
{
int wakeup = 0;
pthread_mutex_lock(&(mbox->mutex));
while(0==mbox->nready)
pthread_cond_wait(&(mbox->not_empty),&(mbox->mutex));

*pmsg = mbox->msg_array[mbox->first];
mbox->first = (mbox->first+1)%mbox->size;


if(mbox->nready == mbox->size)
wakeup = 1;
--(mbox->nready);
pthread_mutex_unlock(&(mbox->mutex));

if(wakeup)
pthread_cond_signal(&(mbox->not_full));
}







posted @ 2012-03-15 20:23  westfly  阅读(2160)  评论(0编辑  收藏  举报