【框架】一种通知到多线程框架
前言
本文记录通过回调函数通知到多线程的框架。
本文链接:李柱明博客-框架:https://www.cnblogs.com/lizhuming/p/15205560.html
主要用于解耦。
实现原理
就是把多个回调函数插入到一个链表中,在对应的地方执行这个链表中的所有回调函数。
用途
通知业务只是该原理的作用之一,更多用途由用户自由发挥。
用途之一的通知:各个业务组建一个回调函数,其内容主要是发送消息或其它 IPC。把业务通知到对应线程去执行。
也可以点到点通知,底层功能通过 ID 区分业务,找到该业务绑定在该功能的回调函数执行。
通知结构体源码
以下结构体可以按需求修改。
struct notifier {
struct notifier *next;
notify_func func;
void *arg;
};
链表管理
采用单向链表管理同一类回调函数。
函数类型
可以按需求修改。
typedef void (*notify_func)(void *, int type, int value);
注册&注销
注册:创建一个通知结构体作为节点,配置好参数。插入单向链表中。
注销:从链表中删除节点,释放通知结构体。
使用
函数就是 void notify(struct notifier *notif, int type, int val)
。
调用该函数把链表 notif
上的回调函数都执行一遍。
参考源码
底层文件,实现注册和注销
/** @file lzm_notifier.c
* @brief 简要说明
* @details 详细说明
* @author lzm
* @date 2021-09-01 12:10:06
* @version v1.1
* @copyright Copyright By lizhuming, All Rights Reserved
* @blog https://www.cnblogs.com/lizhuming/
*
**********************************************************
* @LOG 修改日志:
* v1.1 add lock
**********************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lzm_notifier.h"
/**
* @name add_notifier
* @brief add a new function to be called when something happens.
* @param
* @retval
* @author lzm
*/
int add_notifier(notifier_ctx_t *notifier_ctx_ptr, notify_func func, void *arg)
{
if(notifier_ctx_ptr == NULL || func == NULL)
return -1;
notifier_t *np = NULL;
pthread_mutex_lock(¬ifier_ctx_ptr->lock);
for(np = notifier_ctx_ptr->notif; np != NULL; np = np->next)
{
if(np->func == func && np->arg == arg)
{
pthread_mutex_unlock(¬ifier_ctx_ptr->lock);
return 0; // already exist
}
}
np = (notifier_t *)malloc(sizeof(notifier_t));
if (np == NULL)
{
pthread_mutex_unlock(¬ifier_ctx_ptr->lock);
printf("no mem\n");
return -1;
}
np->next = notifier_ctx_ptr->notif;
np->func = func;
np->arg = arg;
notifier_ctx_ptr->notif = np;
pthread_mutex_unlock(¬ifier_ctx_ptr->lock);
return 0;
}
/**
* @name add_notifier
* @brief remove a function from the list of things to be called when something happens.
* @param
* @retval
* @author lzm
*/
int remove_notifier(notifier_ctx_t *notifier_ctx_ptr, notify_func func, void *arg)
{
if(notifier_ctx_ptr == NULL || notifier_ctx_ptr->notif == NULL || func == NULL)
return -1;
notifier_t *np = NULL;
notifier_t *np_last = NULL;
pthread_mutex_lock(¬ifier_ctx_ptr->lock);
np_last = notifier_ctx_ptr->notif;
np = notifier_ctx_ptr->notif;
while(1)
{
if (np->func == func && np->arg == arg)
{
if(np_last == np)
notifier_ctx_ptr->notif =np->next;
else
np_last->next = np->next;
free(np);
break;
}
if(np->next == NULL)
break;
np_last = np;
np = np->next;
}
pthread_mutex_unlock(¬ifier_ctx_ptr->lock);
return 0;
}
/**
* @name notify
* @brief call a set of functions registered with add_notify. (执行该单向链表中的所有回调函数)
* @param
* @retval
* @author lzm
*/
int notify(notifier_ctx_t *notifier_ctx_ptr, int type, int val)
{
if(notifier_ctx_ptr == NULL)
return -1;
notifier_t *np = NULL;
pthread_mutex_lock(¬ifier_ctx_ptr->lock);
np = notifier_ctx_ptr->notif;
while (np != NULL)
{
(*np->func)(np->arg, type, val);
np = np->next;
}
pthread_mutex_unlock(¬ifier_ctx_ptr->lock);
return 0;
}
/**
* @name notify_init
* @brief 入口func
* @param
* @retval
* @author lzm
*/
int notify_init(notifier_ctx_t *notifier_ctx_ptr)
{
if(notifier_ctx_ptr != NULL)
return -1;
notifier_ctx_ptr = malloc(sizeof(notifier_ctx_t));
if(notifier_ctx_ptr == NULL)
return -2;
memset(notifier_ctx_ptr, 0x00, sizeof(notifier_ctx_t));
pthread_mutex_init(¬ifier_ctx_ptr->lock, NULL);
pthread_mutex_lock(¬ifier_ctx_ptr->lock);
notifier_ctx_ptr->notif = NULL;
pthread_mutex_unlock(¬ifier_ctx_ptr->lock);
return 0;
}
/**
* @name notify_exit
* @brief 出口func
* @param
* @retval
* @author lzm
*/
int notify_exit(notifier_ctx_t *notifier_ctx_ptr)
{
if(notifier_ctx_ptr == NULL)
return -1;
notifier_t *np = NULL;
notifier_t *np_next = NULL;
/* exit notify */
notify(notifier_ctx_ptr, 0, 0);
pthread_mutex_lock(¬ifier_ctx_ptr->lock);
np = notifier_ctx_ptr->notif;
while (np != NULL)
{
np_next = np->next;
free(np);
np = np_next;
}
notifier_ctx_ptr->notif = NULL;
pthread_mutex_unlock(¬ifier_ctx_ptr->lock);
pthread_mutex_destroy(¬ifier_ctx_ptr->lock);
free(notifier_ctx_ptr);
return 0;
}
/* 以下为 demo API, 放到其它文件 */
notifier_ctx_t *lzm_notifier_ctx = NULL;
/**
* @name lzm_register_notifier
* @brief
* @param
* @retval
* @author lzm
*/
int lzm_register_notifier(notify_func func, void *arg)
{
return add_notifier(lzm_notifier_ctx, func, arg);
}
/**
* @name lzm_remove_notifier
* @brief api
* @param
* @retval
* @author lzm
*/
void lzm_remove_notifier(notify_func func, void *arg)
{
remove_notifier(lzm_notifier_ctx, func, arg);
}
/**
* @name lzm_notify
* @brief api
* @param
* @retval
* @author lzm
*/
void lzm_notify(int type, int val)
{
notify(lzm_notifier_ctx, type, val);
}
/**
* @name lzm_notify_init
* @brief api
* @param
* @retval
* @author lzm
*/
void lzm_notify_init(void)
{
notify_init(lzm_notifier_ctx);
}
/**
* @name lzm_notify_exit
* @brief api
* @param
* @retval
* @author lzm
*/
void lzm_notify_exit(void)
{
notify_exit(lzm_notifier_ctx);
}
接口文件
/** @file lzm_notifier.h
* @brief 简要说明
* @details 详细说明
* @author lzm
* @date 2021-09-01 12:10:06
* @version v1.1
* @copyright Copyright By lizhuming, All Rights Reserved
* @blog https://www.cnblogs.com/lizhuming/
*
**********************************************************
* @LOG 修改日志:
* v1.1 add lock
**********************************************************
*/
#ifndef __lzm_notifier_h__
#define __lzm_notifier_h__
#include <pthread.h>
typedef void (*notify_func)(void *, int type, int value);
struct notifier
{
struct notifier *next;
notify_func func;
void *arg;
};
typedef struct notifier notifier_t;
typedef struct
{
pthread_mutex_t lock;
notifier_t *notif;
}notifier_ctx_t;
int add_notifier(notifier_ctx_t *notifier_ctx_ptr, notify_func func, void *arg);
int remove_notifier(notifier_ctx_t *notifier_ctx_ptr, notify_func func, void *arg);
int notify(notifier_ctx_t *notifier_ctx_ptr, int type, int val);
int notify_init(notifier_ctx_t *notifier_ctx_ptr);
int notify_exit(notifier_ctx_t *notifier_ctx_ptr);
/* 以下为demo API, 放到其它文件 */
int lzm_register_notifier(notify_func func, void *arg);
void lzm_remove_notifier(notify_func func, void *arg);
void lzm_notify(int type, int val);
void lzm_notify_init(void);
void lzm_notify_exit(void);
#endif /* Head define end*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!