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