歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux下模擬一個簡易的消息機制

Linux下模擬一個簡易的消息機制

日期:2017/3/1 9:40:50   编辑:Linux編程

消息機制是WIN32的核心,本質就是一個消息結構的鏈表。

聲明

#define MSG_ERROR -1

#define MSG_SUCCEED 0 #define MSG_TRUE 1

#define MSG_FALSE 0 #define PM_NOREMOVE 0x00

#define PM_REMOVE 0x01 typedef unsigned longWPARAM; typedef unsigned longLPARAM; typedef unsigned intUINT; typedef intMSG_BOOL;//這個返回值很二 不要噴我... typedef struct

{

UINTmessage;//消息類型 UINTidThread;//線程ID WPARAMwParam;

LPARAMlParam;

}MSG;

typedef MSG* LPMSG;

typedef struct NODE

{

MSG data;

struct NODE* next;

}MSG_NODE;

void SetupMessage();//啟動消息隊列 void TerminalMessage();//終止消息隊列

MSG_BOOL PeekMessage( LPMSG lpMsg,

UINT hWnd,

UINT wMsgFilterMin,

UINT wMsgFilterMax,

UINT wRemoveMsg);

MSG_BOOL PostThreadMessage( UINT idThread,

UINT msg,

WPARAM wParam,

LPARAM lParam);

實現

#include "msg.h" #include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <assert.h>

#include <pthread.h> static MSG_NODE * g_message_queue = NULL;

static MSG_NODE* msg_create()

{

MSG_NODE* pHead = calloc(sizeof(MSG_NODE),1);

return pHead;

}

static void msg_destroy(MSG_NODE* pHead)

{

MSG_NODE* pNode = NULL;

if(pHead)

{

pNode = pHead->next;

while(pNode)

{

pHead->next = pNode->next;

printf("Free Node:%p\n",pNode);

free(pNode);

pNode = pHead->next;

}

free(pHead);

printf("Free Head Node:%p\n",pHead);

}

}

//定位到消息列表尾部

static MSG_NODE* msg_tail(MSG_NODE* pHead)

{

MSG_NODE* pTail = NULL;

if(!pHead) return NULL;

pTail = pHead;

while(pTail->next) pTail = pTail->next;

return pTail;

}

//尾部插入一個消息結點

static int msg_push_back(MSG_NODE* pHead, MSG_NODE* pNode)

{

MSG_NODE* pTail = NULL;

if( !pHead || !pNode) return MSG_ERROR;

pTail = msg_tail(pHead);

if(pTail)

{

pTail->next = pNode;

pNode->next = NULL;

return MSG_SUCCEED;

}

return MSG_ERROR;

}

//啟動

void SetupMessage()

{

if(!g_message_queue)

{

g_message_queue = msg_create();

assert(g_message_queue);

}

}

//終止

void TerminalMessage()

{

msg_destroy(g_message_queue);

g_message_queue = NULL;

}

MSG_BOOL PostThreadMessage(UINT idThread,UINT msg, WPARAM wParam, LPARAM lParam)

{

MSG_NODE* pNode = NULL;

if( !g_message_queue && (msg < 0) ) return MSG_FALSE;

pNode = calloc(sizeof(MSG_NODE),1);

if (pNode)

{

pNode->data.message = msg;

pNode->data.idThread = (!idThread)?pthread_self():idThread;//如果ID是0 默認為當前線程 pNode->data.wParam = wParam;

pNode->data.lParam = lParam;

pNode->next = NULL;

return (msg_push_back(g_message_queue,pNode) == MSG_SUCCEED)?MSG_TRUE:MSG_FALSE;

}

return MSG_FALSE;

}

//第二個參數完成為了函數"像" Win32 API 沒有用處,LINUX沒有窗口句柄這一說 MSG_BOOL PeekMessage(LPMSG lpMsg,UINT HWND,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg)

{

MSG_NODE* pNode = NULL;

MSG_NODE* pPreNode = NULL;//保存前一個結點

if( !g_message_queue && lpMsg) return MSG_FALSE;

pPreNode = g_message_queue;

pNode = g_message_queue->next;

/*

*不要噴我 用這麼多goto啊 只是為了 不要寫一堆重復的代碼

*/

while(pNode)

{

if(pNode->data.idThread != (UINT)pthread_self() )

{

goto NEXT;

}

if(wMsgFilterMin|wMsgFilterMax)

{

if( pNode->data.message >= wMsgFilterMin &&

pNode->data.message <= wMsgFilterMax )

{

goto GET_MSG;

}

}

else

{

goto GET_MSG;

}

NEXT:

pPreNode = pNode;

pNode = pNode->next;

continue;

GET_MSG:

memcpy(lpMsg,&pNode->data,sizeof(MSG) );

if(wRemoveMsg == PM_REMOVE)//刪除消息鏈表結點 {

pPreNode->next = pNode->next;//前驅結點關聯後繼結點 防止鏈表截斷 free(pNode);//釋放當前消息鏈表結點 }

return MSG_TRUE;

}

return MSG_TRUE;

}

測試用例


#include <stdio.h>

#include <string.h>

#include "msg.h"

int main(int argc,char** argv)

{

int i=0;

MSG msg;

SetupMessage();

for(i=0;i<10;i++)

{

PostThreadMessage(0,1000+i, 100+i, 200+i);

}

while(1)

{

PeekMessage(&msg,0,0,0,PM_REMOVE);

printf("ID:%u,WPARAM:%lu,LPARAM:%lu\n",msg.message,msg.wParam,msg.lParam);

if(!msg.message)break;

memset(&msg,0,sizeof(MSG));

sleep(2);

}

TerminalMessage();

return 0;

}

測試用例只是做了一些簡單基礎的測試,並不完善。

除了線程相關的系統調用,全部采用標准庫實現。

Copyright © Linux教程網 All Rights Reserved