消息队列

#pragma once
#include <windows.h>
#include <iostream>
using namespace std;

#define TASK_NO_EXIT      0
#define TASK_EXIT         1

#define  DEFAULT_MSGQUEUE_LENGTH 10

#define MYCreateSemaphore(x,y)     CreateSemaphore(NULL,x,y,NULL)
#define MYWaitForSingleObject(x)   WaitForSingleObject(x,INFINITE)   //灭灯 
#define MYReleaseSemaphore(x,y)    ReleaseSemaphore(x,y,NULL)        //点灯
#define MYCloseHandle(x)           CloseHandle(x)
#define MYCreateMutex()            CreateMutex(NULL, FALSE, NULL)
#define MYReleaseMutex(x)          ReleaseMutex(x)
#define MYCreateEvent()            CreateEvent(NULL, TRUE, FALSE, NULL)


typedef struct _DOUBLE_NODE_ {
	struct _DOUBLE_NODE_ *Flink;     /* 下一个节点指针 */
	struct _DOUBLE_NODE_ *Blink;     /* 前一个节点指针 */
	void   *BufferData;                    /* 数据指针 */
}DOUBLE_NODE,*PDOUBLE_NODE;

typedef struct _DOUBLE_LIST_ {
	PDOUBLE_NODE HeadNode;     /* 第1个节点的指针 */
	PDOUBLE_NODE TailNode;     /* 最后1个节点的指针 */
	UINT         NodeCount;    /* 保存链表节点的个数 */
}DOUBLE_LIST, *PDOUBLE_LIST;

typedef struct _EXIT_TASK_
{
	HANDLE      MutexHandle;        /* 操作锁 */
	UINT        ExitFlag;         /* 退出标志 */
}EXIT_TASK,*PEXIT_TASK;
typedef struct  _TASK_NODE_
{
	PDOUBLE_LIST DoubleList;    /* 双向链表指针 */
	PEXIT_TASK   ExitTask;         /* 多任务退出结构指针 */
}TASK_NODE,*PTASK_NODE;
typedef struct _MSG_QUEUE_{
	PTASK_NODE TaskNode;           /* 多任务链表 */
	HANDLE     SemaphoreHandleHandle;                /* 处理队列为空情况的计数信号量*/
	UINT       MaxLength;         /* 队列的最大长度 */
}MSG_QUEUE,*PMSG_QUEUE;









typedef void (*LPFN_DESTROYFUNCTION) (void* BufferData);




PMSG_QUEUE   MsgQueue_Create(INT MaxLength);
PTASK_NODE   TaskList_Create(void);
PDOUBLE_LIST DoubleList_Create(void);
PEXIT_TASK   ExitTask_Create();
void MsgQueue_Destroy(PMSG_QUEUE MsgQueue, LPFN_DESTROYFUNCTION DestroyFunction);
void TaskList_Destroy(PTASK_NODE TaskNode, LPFN_DESTROYFUNCTION DestroyFunction);
void DoubleList_Destroy(PDOUBLE_LIST DoubleList, LPFN_DESTROYFUNCTION DestroyFunction);
void ExitTask_Destroy(PEXIT_TASK ExitTask);
BOOL MsgQueue_Entern(PMSG_QUEUE MsgQueue, void* BufferData);
BOOL TaskList_Entern(PTASK_NODE TaskNode, void* BufferData);
BOOL DoubleList_Entern(PDOUBLE_LIST DoubleList, void* BufferData);
void* MsgQueue_Leave(PMSG_QUEUE MsgQueue);
void* TaskList_Leave(PTASK_NODE TaskNode);
void* DoubleList_Leave(PDOUBLE_LIST DoubleList);

  

#include"_MsgQueue.h"

//创建消息队列
PMSG_QUEUE  MsgQueue_Create(INT MaxLength)
{
	PMSG_QUEUE  MsgQueue = NULL;

	MsgQueue = (PMSG_QUEUE)malloc(sizeof(MSG_QUEUE));
	if (MsgQueue != NULL)
	{
		MsgQueue->SemaphoreHandleHandle = MYCreateSemaphore(0, MaxLength);
		if (MsgQueue->SemaphoreHandleHandle != NULL)
		{
			MsgQueue->MaxLength = MaxLength;
			MsgQueue->TaskNode = TaskList_Create();
			if (MsgQueue->TaskNode == NULL)
			{
				MYCloseHandle(MsgQueue->SemaphoreHandleHandle);
				free(MsgQueue);
				MsgQueue = NULL;
			}
		}
		else
		{
			free(MsgQueue);
			MsgQueue = NULL;
		}
	}
	return MsgQueue;
}

PTASK_NODE TaskList_Create(void)
{
	PTASK_NODE  TaskNode = NULL;
	TaskNode = (PTASK_NODE)malloc(sizeof(TASK_NODE));
	if (TaskNode != NULL)
	{
		TaskNode->DoubleList = DoubleList_Create();//创建双向链表
		if (TaskNode->DoubleList != NULL)
		{
			TaskNode->ExitTask = ExitTask_Create();
			if (TaskNode->ExitTask == NULL)
			{
				free(TaskNode->DoubleList);
				free(TaskNode);
				TaskNode = NULL;
			}
		}
		else
		{
			free(TaskNode);
			TaskNode = NULL;
		}
	}
	return TaskNode;
}

PDOUBLE_LIST DoubleList_Create(void)
{
	PDOUBLE_LIST DoubleList = NULL;

	/* 分配内存操作 */
	DoubleList = (PDOUBLE_LIST )malloc(sizeof(DOUBLE_LIST));
	if (DoubleList != NULL)
	{
		/* 初始化链表结构体各指针成员为空,链表节点个数为0 */
		DoubleList->HeadNode = NULL;
		DoubleList->TailNode = NULL;
		DoubleList->NodeCount = 0;
	}

	return DoubleList;
}

PEXIT_TASK   ExitTask_Create()
{
	PEXIT_TASK  ExitTask = NULL;

	ExitTask = (PEXIT_TASK)malloc(sizeof(EXIT_TASK));

	if (ExitTask != NULL)
	{
		ExitTask->MutexHandle = MYCreateMutex();
		if (ExitTask->MutexHandle == NULL)
		{
			free(ExitTask);
			return NULL;
		}
	
		ExitTask->ExitFlag = TASK_NO_EXIT;
	}
	return ExitTask;
}

void MsgQueue_Destroy(PMSG_QUEUE MsgQueue, LPFN_DESTROYFUNCTION DestroyFunction)
{
	if (MsgQueue != NULL)
	{
		INT MaxLength = 0;
		if (MsgQueue->MaxLength > DEFAULT_MSGQUEUE_LENGTH)//当最大长度大于
		{
			MaxLength = MsgQueue->MaxLength;
		}
		else
		{
			MaxLength = DEFAULT_MSGQUEUE_LENGTH;
		}
		MYReleaseSemaphore(MsgQueue->SemaphoreHandleHandle, MaxLength); /* 让所有阻塞的接收操作可以继续*/
	

		TaskList_Destroy(MsgQueue->TaskNode, DestroyFunction);
		MYCloseHandle(MsgQueue->SemaphoreHandleHandle);
		free(MsgQueue);
	}
}
void TaskList_Destroy(PTASK_NODE TaskNode, LPFN_DESTROYFUNCTION DestroyFunction)
{

	if (TaskNode == NULL)
	{
		return;
	}

	ExitTask_Destroy(TaskNode->ExitTask);

	DoubleList_Destroy(TaskNode->DoubleList, DestroyFunction);

	free(TaskNode);

}
void DoubleList_Destroy(PDOUBLE_LIST DoubleList, LPFN_DESTROYFUNCTION DestroyFunction)
{
	PDOUBLE_NODE TravleNode = NULL;

	if (DoubleList)
	{
		/* 从头节点开始,一个接一个释放链表节点及节点数据 */
		TravleNode = DoubleList->HeadNode;//临时变量用于接收将要被删除的节点
		while (TravleNode != NULL)
		{
			PDOUBLE_NODE DeleteNode = NULL;

			DeleteNode = TravleNode;
			TravleNode = TravleNode->Flink;

			if (DestroyFunction != NULL && DeleteNode->BufferData != NULL)
			{
				/* 释放数据 */
				(*DestroyFunction)(DeleteNode->BufferData);//通过传进来的函数指针删除真正存储的数据
			}
			free(DeleteNode); /* 释放节点 */
		}
		/* 释放链表结构体 */
		free(DoubleList);
	}
}
void ExitTask_Destroy(PEXIT_TASK ExitTask)
{
	MYWaitForSingleObject(ExitTask->MutexHandle);

	ExitTask->ExitFlag = TASK_EXIT;


	
	MYReleaseMutex(ExitTask->MutexHandle);

	/* 关闭操作的锁和退出事件 */
	MYCloseHandle(ExitTask->MutexHandle);

	free(ExitTask);
}
BOOL MsgQueue_Entern(PMSG_QUEUE MsgQueue, void* BufferData)
{
	BOOL  IsOk;

	IsOk = TaskList_Entern(MsgQueue->TaskNode, BufferData);   //由于是Queue所以采用 Tail插入 先进先出


	//限制入队情况
	MYReleaseSemaphore(MsgQueue->SemaphoreHandleHandle, 1); /* 将计数加1,当数量达到限制值,将会阻塞等待其他线程释放信号量 */

	return IsOk;
}
BOOL TaskList_Entern(PTASK_NODE TaskNode, void* BufferData)
{
	BOOL IsOk;

	MYWaitForSingleObject(TaskNode->ExitTask->MutexHandle);

	IsOk = DoubleList_Entern(TaskNode->DoubleList, BufferData);

	MYReleaseMutex(TaskNode->ExitTask->MutexHandle);

	return IsOk;
}
BOOL DoubleList_Entern(PDOUBLE_LIST DoubleList, void* BufferData)
{
	PDOUBLE_NODE NewNode = NULL;


    /* 参数校验 */
    if ( DoubleList == NULL || BufferData == NULL )
    {
        return FALSE;
    }

    /* 新建一个节点 */
    NewNode = (PDOUBLE_NODE)malloc( sizeof(DOUBLE_NODE));
    if ( NewNode == NULL )
    {
        return FALSE;
    }
 
	NewNode->BufferData = BufferData;  /* 将节点数据指针指向传进来的数据 */
    NewNode->Flink = NULL;             /* 将节点的下一节点赋为空指针NULL */
   
	
	NewNode->Blink = DoubleList->TailNode;      

    /*
     * 判断是否尾节点指针为空,如果为空表示原来链表中没有节点,
     * 此时应该将尾节点指向新加入的节点, 并且头节点指针也应该指向新节点 
     */
    if ( DoubleList->TailNode == NULL )
    {
        DoubleList->HeadNode = NewNode;
    }
    else
    {
        /*
         * 如果尾节点指针不为空,此时应该将尾节点下一节点指针指向新加入的 
         * 节点,并且尾节点指针也应该指向新节点 
         */
        DoubleList->TailNode->Flink = NewNode;
    }

    DoubleList->TailNode = NewNode;

    /* 将链表节点数据加1 */
    DoubleList->NodeCount++;
    
    return TRUE;
}
void* MsgQueue_Leave(PMSG_QUEUE MsgQueue)
{
	MYWaitForSingleObject(MsgQueue->SemaphoreHandleHandle); /* 将计数减1,计数为0则会阻塞住 */
	return TaskList_Leave(MsgQueue->TaskNode);

}

void * TaskList_Leave(PTASK_NODE TaskNode)
{
	void * BufferData;

	MYWaitForSingleObject(TaskNode->ExitTask->MutexHandle);

	BufferData = DoubleList_Leave(TaskNode->DoubleList);

	MYReleaseMutex(TaskNode->ExitTask->MutexHandle);

	return BufferData;
}
void* DoubleList_Leave(PDOUBLE_LIST DoubleList)
{
	PDOUBLE_NODE   PopNode;   /* 用来指向要弹出数据的节点的指针 */
	void*          BufferData;   /* 用来指向要弹出的数据的指针 */

    /* 参数校验 */
    if ( DoubleList == NULL || DoubleList->HeadNode == NULL ) 
    {
		return NULL;
    }

    /* 将要弹出数据的节点指针指向链表头节点,弹出数据指针指向头节点的数据 */
    PopNode = DoubleList->HeadNode;
    BufferData = PopNode->BufferData;

   

    /* 将头节点指针指向头节点的下一节点 */
    DoubleList->HeadNode = DoubleList->HeadNode->Flink;
    if ( DoubleList->HeadNode != NULL )
    {
        DoubleList->HeadNode->Blink = NULL;
    }
	
    /* 将链表节点数量减1 */
    DoubleList->NodeCount--;

    /* 如果链表的节点数量已经为0则表示原来只有一个节点,弹出头节点后,
     * 此时链表已经为空,没有节点在里面,此时应该将尾节点指针赋空
     * 当前节点指针由于前面已经处理过了,如果只有一个节点的话肯定为空
     * 所以这里不需要处理当前节点指针
     */
    if ( DoubleList->NodeCount == 0 ) {
		DoubleList->TailNode = NULL;
	}
	
    /* 释放弹出的节点, 注意这里并没有释放节点数据指针 */
    free( PopNode );

    return BufferData;    /* 返回头节点的数据指针 */
}

  

// 消息队列.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "_MsgQueue.h"

#include <process.h>
#define  MAX_THREADS 5
struct _DATA_ 
{
	char Name[20];
	int  Age;
}__Data[5] = { {"刘德华",27},{"张学友",25},{"陈奕迅",21},{"杨宗纬",25},{"林宥嘉",17}};

//自定义函数
void DestroyFunction(char* BufferData);
void EnterQueueProcedure(void* ParameterData);
void OutQueueProcedure(void* ParameterData);

PMSG_QUEUE __MsgQueue = NULL;
int main()
{
	HANDLE ThreadHandle[MAX_THREADS + 1] = { NULL };
	__MsgQueue = MsgQueue_Create(DEFAULT_MSGQUEUE_LENGTH);
	if (__MsgQueue==NULL)
	{
		return 0;
	}
	int i = 0;
	ThreadHandle[0] = (HANDLE)_beginthread(OutQueueProcedure, 0, NULL);   
	for (i = 0; i < MAX_THREADS; i++)
	{
		ThreadHandle[i+1]= (HANDLE)_beginthread(EnterQueueProcedure, 0, (void*)i);
	}

	WaitForMultipleObjects(MAX_THREADS + 1, ThreadHandle, TRUE, 5000);

	for (i = 0; i < MAX_THREADS+1; i++)
	{
		TerminateThread(ThreadHandle[i],0);
		ThreadHandle[i] = NULL;
	}


	if (__MsgQueue!=NULL)
	{
		MsgQueue_Destroy(__MsgQueue,(LPFN_DESTROYFUNCTION)DestroyFunction);
		__MsgQueue = NULL;
	}

	
	printf("Input AnyKey To Exit\r\n");
	getchar();

    return 0;
}

void EnterQueueProcedure(void* ParameterData)
{
	_DATA_* BufferData = new _DATA_;
	memcpy(BufferData, &__Data[(int)ParameterData], sizeof(_DATA_));
	MsgQueue_Entern(__MsgQueue,BufferData);
}


void OutQueueProcedure(void* ParameterData)
{

	void* BufferData = NULL;
	while (1)
	{
		BufferData = MsgQueue_Leave(__MsgQueue);

		if (BufferData!=NULL)
		{
			printf("%s   %d\r\n", ((_DATA_*)BufferData)->Name,
				((_DATA_*)BufferData)->Age);
		}
	}
}



void DestroyFunction(char* BufferData)
{
	if (BufferData!=NULL)
	{
		delete BufferData;
		BufferData = NULL;
	}
}

  

原文地址:https://www.cnblogs.com/Crisczy/p/7401299.html