整个订阅发布事件机制,引入两个东西:EventHub和EventNode。
整个订阅发布事件机制围绕着EventHub和EventNode,特点:
SPEvent采用双向链表进行维护整个订阅-发布逻辑
函数 | 说明 |
---|---|
SPEventInit | 初始化函数 |
SPEventDeinit | 去初始化函数 |
SPEventSubscribe | 订阅事件函数 |
SPEventUnsubscribe | 注销订阅事件函数 |
SPEventPublish | 发布事件消息 |
SPEventClear | 清除事件池 |
RecvtInfoDump | 导出事件池信息 |
#ifndef __SPEVENT_DEF_H__
#define __SPEVENT_DEF_H__
#include
#include
#include
#include
#include
#include
#include
#define SPEVENT_INLINE static __inline
#define SPEVENT_EVENT_NAME_LEN 16
#ifndef SPEVENT_MALLOC
#define SPEVENT_MALLOC malloc
#endif
#ifndef SPEVENT_FREE
#define SPEVENT_FREE free
#endif
#ifndef SPEVENT_PRINT
#define SPEVENT_PRINT printf
#endif
struct SPEventListNode
{
struct SPEventListNode *next;
struct SPEventListNode *prev;
};
typedef struct SPEventListNode SPEventList;
SPEVENT_INLINE void SPEVENT_LIST_INIT(SPEventList *l)
{
l->next = l->prev = l;
}
SPEVENT_INLINE void SPEVENT_LIST_INSERT_AFTER(SPEventList *l, SPEventList *n)
{
l->next->prev = n;
n->next = l->next;
l->next = n;
n->prev = l;
}
SPEVENT_INLINE void SPEVENT_LIST_INSERT_BEFORE(SPEventList *l, SPEventList *n)
{
l->prev->next = n;
n->prev = l->prev;
l->prev = n;
n->next = l;
}
SPEVENT_INLINE void SPEVENT_LIST_REMOVE(SPEventList *n)
{
n->next->prev = n->prev;
n->prev->next = n->next;
n->next = n->prev = n;
}
SPEVENT_INLINE int SPEVENT_LIST_LEN(const SPEventList *l)
{
int len = 0;
const SPEventList *p = l;
while (p->next != l) {
p = p->next;
len ++;
}
return len;
}
#define SPEVENT_CONTAINER_OF(ptr, type, member)
((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
#define SPEVENT_LIST_OBJ_INIT(obj) {&(obj), &(obj)}
#define SPEVENT_LIST_ENTRY(node, type, member)
SPEVENT_CONTAINER_OF(node, type, member)
#define SPEVENT_LIST_FOR_EACH(pos, head)
for (pos = (head)->next; pos != (head); pos = pos->next)
#define SPEVENT_LIST_FOR_EACH_SAFE(pos, n, head)
for (pos = (head)->next, n = pos->next; pos != (head);
pos = n, n = pos->next)
#define SPEVENT_LIST_FOR_EACH_ENTRY(pos, head, member)
for (pos = SPEVENT_LIST_ENTRY((head)->next, typeof(*pos), member);
&pos->member != (head);
pos = SPEVENT_LIST_ENTRY(pos->member.next, typeof(*pos), member))
#define SPEVENT_LIST_FOR_EACH_ENTRY_SAFE(pos, n, head, member)
for (pos = SPEVENT_LIST_ENTRY((head)->next, typeof(*pos), member),
n = SPEVENT_LIST_ENTRY(pos->member.next, typeof(*pos), member);
&pos->member != (head);
pos = n, n = SPEVENT_LIST_ENTRY(n->member.next, typeof(*n), member))
#define SPEVENT_LIST_FIRST_ENTRY(ptr, type, member)
SPEVENT_LIST_ENTRY((ptr)->next, type, member)
#endif
#include "spevent.h"
static SPEventList g_hublist = {0};
static SPEventHubNode *SPEventFindHubNode(SPEventList *list, const char *event)
{
SPEventHubNode *hubNode = NULL;
SPEventList *node = NULL;
SPEVENT_LIST_FOR_EACH(node, list) {
hubNode = SPEVENT_LIST_ENTRY(node, SPEventHubNode, hubList);
if(hubNode != NULL && strcmp(hubNode->event, event) == 0) {
return hubNode;
}
}
return NULL;
}
static SPEventEventNode *SPEventFindEventNode(SPEventList *eventList, SPEventHandle handle)
{
SPEventEventNode *eventNode = NULL;
SPEventList *node = NULL;
SPEVENT_LIST_FOR_EACH(node, eventList) {
eventNode = SPEVENT_LIST_ENTRY(node, SPEventEventNode, list);
if(eventNode != NULL && handle == eventNode->handle) {
return eventNode;
}
}
return NULL;
}
SPEventEventNode *SPEventSubscribe(const char *event, SPEventHandle handle)
{
SPEventHubNode *hubNode = NULL;
SPEventEventNode *eventNode = NULL;
hubNode = SPEventFindHubNode(&g_hublist, event);
if(hubNode == NULL) {
hubNode = (SPEventHubNode *)SPEVENT_MALLOC(sizeof(SPEventHubNode));
if(hubNode == NULL) {
SPEVENT_PRINT("SPEVENT hub(%s) malloc failedrn", event);
return NULL;
}
memset(hubNode->event, 0, SPEVENT_EVENT_NAME_LEN);
memcpy(hubNode->event, event, strlen(event));
SPEVENT_LIST_INSERT_AFTER(&g_hublist, &(hubNode->hubList));
SPEVENT_LIST_INIT(&(hubNode->eventList));
}
eventNode = (SPEventEventNode *)SPEVENT_MALLOC(sizeof(SPEventEventNode));
if(eventNode == NULL) {
SPEVENT_PRINT("SPEVENT event(%s) malloc failedrn", event);
return NULL;
}
eventNode->handle = handle;
SPEVENT_LIST_INSERT_AFTER(&hubNode->eventList, &(eventNode->list));
SPEVENT_PRINT("SPEVENT event(%s) Subscribe successrn", event);
return eventNode;
}
bool SPEventUnsubscribe(const char *event, SPEventEventNode *node)
{
SPEventHubNode *hubNode = NULL;
SPEventEventNode *eventNode = NULL;
hubNode = SPEventFindHubNode(&g_hublist, event);
if(hubNode == NULL) {
SPEVENT_PRINT("SPEVENT hub(%s) find failedrn", event);
return false;
}
eventNode = SPEventFindEventNode(&(hubNode->eventList), node->handle);
if(eventNode == NULL) {
SPEVENT_PRINT("SPEVENT event(%s) find failedrn", event);
return false;
}
SPEVENT_LIST_REMOVE(&(eventNode->list));
SPEVENT_FREE(eventNode);
eventNode = NULL;
SPEVENT_PRINT("SPEVENT event(%s) Unsubscribe successrn", event);
return true;
}
bool SPEventPublish(const char *event, void *payload)
{
SPEventHubNode *hubNode = NULL;
SPEventEventNode *eventNode = NULL;
SPEventList *node = NULL;
hubNode = SPEventFindHubNode(&g_hublist, event);
if(hubNode == NULL) {
SPEVENT_PRINT("SPEVENT hub(%s) find failedrn");
return false;
}
SPEVENT_LIST_FOR_EACH(node, &(hubNode->eventList)) {
eventNode = SPEVENT_LIST_ENTRY(node, SPEventEventNode, list);
if(eventNode->handle) {
eventNode->handle(event, payload);
}
}
SPEVENT_PRINT("SPEVENT event(%s) Publish successrn", event);
return true;
}
void SPEventClear(void)
{
SPEventHubNode *hubNode = NULL;
SPEventEventNode *eventNode = NULL;
SPEventList *hubList = NULL;
SPEventList *eventList = NULL;
SPEVENT_LIST_FOR_EACH(hubList, &g_hublist) {
hubNode = SPEVENT_LIST_ENTRY(hubList, SPEventHubNode, hubList);
if(hubNode == NULL) {
continue;
}
SPEVENT_LIST_FOR_EACH(eventList, &(hubNode->eventList)) {
eventNode = SPEVENT_LIST_ENTRY(eventList, SPEventEventNode, list);
if(eventNode == NULL) {
continue;
}
SPEVENT_LIST_REMOVE(&(eventNode->list));
SPEVENT_FREE(eventNode);
eventNode = NULL;
}
SPEVENT_LIST_REMOVE(&(hubNode->hubList));
SPEVENT_FREE(hubNode);
hubNode = NULL;
}
}
void RecvtInfoDump(void)
{
SPEventHubNode *hubNode = NULL;
SPEventEventNode *eventNode = NULL;
SPEventList *hubList = NULL;
SPEventList *eventList = NULL;
int eventNodeCount = 0;
SPEVENT_PRINT("SPEVENT list: rn");
SPEVENT_LIST_FOR_EACH(hubList, &g_hublist) {
hubNode = SPEVENT_LIST_ENTRY(hubList, SPEventHubNode, hubList);
if(hubNode == NULL) {
continue;
}
SPEVENT_PRINT("SPEVENT event(%s): ", hubNode->event);
eventNodeCount = 0;
SPEVENT_LIST_FOR_EACH(eventList, &(hubNode->eventList)) {
eventNode = SPEVENT_LIST_ENTRY(eventList, SPEventEventNode, list);
if(eventNode == NULL) {
continue;
}
eventNodeCount++;
}
SPEVENT_PRINT("%drn", eventNodeCount);
}
}
void SPEventInit(void)
{
SPEVENT_LIST_INIT(&g_hublist);
}
void SPEventDeinit(void)
{
SPEventClear();
}
#ifndef __SPEVENT_H__
#define __SPEVENT_H__
#include "spevent_def.h"
typedef void (*SPEventHandle)(const char *event, void *payload);
typedef struct
{
SPEventHandle handle;
SPEventList list;
}SPEventEventNode;
typedef struct
{
char event[SPEVENT_EVENT_NAME_LEN];
SPEventList eventList;
SPEventList hubList;
}SPEventHubNode;
void SPEventInit(void);
void SPEventDeinit(void);
SPEventEventNode *SPEventSubscribe(const char *event, SPEventHandle handle);
bool SPEventUnsubscribe(const char *event, SPEventEventNode *node);
bool SPEventPublish(const char *event, void *payload);
void SPEventClear(void);
void RecvtInfoDump(void);
#endif
#include
void SPEventHandle1(const char *event, void *payload)
{
SPEVENT_PRINT("Event1: %s, payload: %s", event, payload);
}
void SPEventHandle2(const char *event, void *payload)
{
SPEVENT_PRINT(ent2: %s, payload: %s", event, payload);
}
int main()
{
SPEventInit();
SPEventEventNode *eventNode1 = SPEventSubscribe("Rice", SPEventHandle1);
if(eventNode1 != NULL)
{
SPEventPublish("Rice", "hello");
} else {
rlog_e("SPEVENT subscribe event failed");
}
SPEventEventNode *eventNode2 = SPEventSubscribe("Rice", SPEventHandle2);
if(eventNode2 != NULL)
{
SPEventPublish("Rice", "world");
} else {
rlog_e("SPEVENT subscribe event failed");
}
RecvtInfoDump();
SPEventUnsubscribe("Rice", eventNode1);
SPEventPublish("Rice", "Hello world");
RecvtInfoDump();
return 0;
}
SPEVENT event(Rice) Subscribe success
Event1: Rice, payload: hello
SPEVENT event(Rice) Publish success
SPEVENT event(Rice) Subscribe success
Event2: Rice, payload: world
Event1: Rice, payload: world
SPEVENT event(Rice) Publish success
SPEVENT list:
SPEVENT event(Rice): 2
SPEVENT event(Rice) Unsubscribe success
Event2: Rice, payload: Hello world
SPEVENT event(Rice) Publish success
SPEVENT list:
SPEVENT event(Rice): 1
全部0条评论
快来发表一下你的评论吧 !