window下简单的生产者和单一消费的程序
使用window下的事件和临界区实现,
在Linux可以使用条件变量和互斥锁实现,
简单的代码如下:
#ifndef _MSGQUEUE_
#define _MSGQUEUE_
///
//消息队列节点
//
#include <Windows.h>
#define MY_X_LOCK(x) EnterCriticalSection(x)
#define MY_X_UNLOCK(x) LeaveCriticalSection(x)
#define MY_X_LOCK_INIT(x) InitializeCriticalSection(x)
#define MY_X_LOCK_DEINIT(x) DeleteCriticalSection(x)
#define MY_COND_WIAT( XHanle , block_time_ms ) WaitForSingleObject(XHanle , block_time_ms)
#define MY_COND_CREATE() CreateEvent(NULL,TRUE,FALSE, NULL)
#define MY_COND_SEND(x) SetEvent(x)
#define MY_COND_DESTROY(x) CloseHandle(x)
//
//使用指针传参
//
template <typename Object>
class MSGQueue {
public:
MSGQueue(int size):theSize(size){ init(); }
~MSGQueue(){ clear(); }
/*
*push data to queue
*/
void push( Object& x)
{
//::pthread_mutex_lock(&m_pushLock); //for linux
//printf(" push ---->>>>(%#x) \n",(long)workqWp);
MY_X_LOCK(&m_wlock);
//MY_X_LOCK(&workqWp->qlock);
//保护临界资源
if(workqWp->writable ){
workqWp->data = x;
workqWp->writable = 0x00;
//MY_X_UNLOCK(&workqWp->qlock);
MY_COND_SEND(workqWp->qready);
workqWp = workqWp->next;
}
else {
printf("buffer full \n");
}
MY_X_UNLOCK(&m_wlock);
}
/*
*add by lqh
*block_time_ms : unit is ms.
*/
int front(Object& x, long block_time_ms)
{
int ret = -1;
//MY_X_LOCK(&workqRp->qlock);
if(workqRp->writable)
{
if ( block_time_ms < 0 ) {
MY_COND_WIAT(workqRp->qready ,INFINITE);
ResetEvent(workqRp->qready);//重置为无信号状态
if ( !workqRp->writable ) {
x = workqRp->data;
workqRp->writable = 0x01;
ret = 0;
}
//MY_X_UNLOCK(&workqRp->qlock);
if(ret == 0 ){
workqRp = workqRp->next;
}
return ret;
}
else{
//
//等待信号被触发 阻塞等待,超时时间 block_time_ms 毫秒
//
if(MY_COND_WIAT(workqRp->qready, block_time_ms) != WAIT_OBJECT_0) {
ResetEvent(workqRp->qready);//重置为无信号状态
//printf("unlock timeout \n");
//MY_X_UNLOCK(&workqRp->qlock);
return -1;
}else {
//printf("fffff->\n");
ResetEvent(workqRp->qready);//重置为无信号状态
//
//此时workqRp->qlock 已经被释放了
//
if ( !workqRp->writable ) {
x = workqRp->data;
workqRp->writable = 0x01;
ret = 0;
}
//MY_X_UNLOCK(&workqRp->qlock);
if(ret == 0 ){
workqRp = workqRp->next;
}
return ret;
}
}
}
else {
if ( !workqRp->writable ) {
x = workqRp->data;
workqRp->writable = 0x01;
ret = 0;
}
//MY_X_UNLOCK(&workqRp->qlock);
if(ret == 0 ){
workqRp = workqRp->next;
}
}
return ret;
}
private:
void init()
{
int i =0;
Node* temp;
workq = static_cast<struct Node*>(::malloc( sizeof(struct Node) * theSize ));
/*
*create a rink buffer !
*/
temp = workq;
do{
temp->writable = 0x01;
temp->qready = MY_COND_CREATE();
//MY_X_LOCK_INIT (&temp->qlock);
if(i == (theSize - 1)){
temp->next = workq;
}
else{
temp->next = (Node*)((char*)temp + sizeof(Node));
temp = temp->next;
}
i ++;
}while( i < theSize);
workqRp = workq;
workqWp = workq;
MY_X_LOCK_INIT(&m_wlock);
}
void clear()
{
Node* temp = workq->next;
while(workq != temp) {
MY_X_LOCK_DEINIT(&temp->qlock);
MY_COND_DESTROY(temp->qready);
temp = temp->next;
}
free(workq);
MY_X_LOCK_DEINIT(&m_wlock);
}
private:
struct Node{
Object data;
HANDLE qready;//
//CRITICAL_SECTION qlock; // mutex
int writable;
Node* next;
Node(const Object& d = Object() , Node* n = NULL):data(d) ,next(n) ,writable(1){}
};
int theSize;
Node *workq ;
Node *workqRp ;
Node *workqWp ;
CRITICAL_SECTION m_wlock;
};
#endif
下面是测试子程序
// code.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "msgQueue.h"
//
//
CRITICAL_SECTION wlock;
int i = 1;
typedef struct {
int _conut;
char _string[128];
}messageNode;
class message{
public:
message(){m_message = NULL;}
~message(){if(m_message) free(m_message);}
void* GetMessage(){return m_message;}
void ResetMessage(int len) {
if(m_message) free(m_message);
m_message = (void*)malloc(len);
memset(m_message, 0, len);
}
private:
void* m_message;
int len;
};
DWORD WINAPI MYProducerThread(LPVOID);
DWORD WINAPI MYConsumerThread(LPVOID);
int _tmain(int argc, _TCHAR* argv[])
{
InitializeCriticalSection(&wlock);
HANDLE handle[3];
MSGQueue<message*>* g_msgQueue = new MSGQueue<message*>(10); //多线程共享该队列
handle[0] = CreateThread(NULL, 0, MYProducerThread, g_msgQueue, 0, NULL); //生产者线程1
handle[1] = CreateThread(NULL, 0, MYProducerThread, g_msgQueue, 0, NULL); //生产者线程2
handle[2] = CreateThread(NULL, 0, MYConsumerThread, g_msgQueue, 0, NULL); //消费者线程3
while(1){
Sleep(1000);
}
return 0;
}
DWORD WINAPI MYProducerThread(LPVOID param)
{
MSGQueue<message*>* g_msgQueue = (MSGQueue<message*>*)param;
while(1) {
MY_X_LOCK(&wlock);
message* msg = new message();
messageNode* messageData;
msg->ResetMessage(sizeof(messageNode));
messageData = (messageNode*)msg->GetMessage();
messageData->_conut = i++;
sprintf(messageData->_string,"this 第 %d 生产 ",messageData->_conut);
printf("producer: %d, %s \n", messageData->_conut, messageData->_string);
g_msgQueue->push(msg);
MY_X_UNLOCK(&wlock);
//g_msgQueue->push()
Sleep(100);
}
}
DWORD WINAPI MYConsumerThread(LPVOID param)
{
MSGQueue<message*>* g_msgQueue = (MSGQueue<message*>*)param;
int i = 1;
while(1) {
message* msg;
if(g_msgQueue->front( msg,50) == 0) {
messageNode* messageData;
messageData = (messageNode*)msg->GetMessage();
printf("%d, %s \n", messageData->_conut, messageData->_string);
delete msg;
}
else {
printf("time out \n");
}
}
}