• 消息队列


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

      

  • 相关阅读:
    JavaScript Eval 函数使用
    WPFToolkit Calendar & DatePicker 使用介绍
    Windows Mobile 6.5 配置环境,数据库访问,部署简单实例
    ThreadPool.QueueUserWorkItem 方法 (WaitCallback)
    Windws Mobile 6.5 Professional ADO.NET数据访问
    WPF调用Web Services
    c#中Interface的理解
    PagesSection.MaintainScrollPositionOnPostBack 属性
    EclipseRCP中文语言包版本不一致,导致导出错误
    SWT美化开源控件网站
  • 原文地址:https://www.cnblogs.com/Crisczy/p/7401299.html
Copyright © 2020-2023  润新知