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