Linux下模拟一个简易的消息机制
声明
#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 long WPARAM; typedef unsigned long LPARAM; typedef unsigned int UINT; typedef int MSG_BOOL;//这个返回值很二 不要喷我... typedef struct { UINT message;//消息类型 UINT idThread;//线程ID WPARAM wParam; LPARAM lParam; }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; }
测试用例只是做了一些简单基础的测试,并不完善。
除了线程相关的系统调用,全部采用标准库实现。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。