前言
本文記錄通過回撥函式通知到多執行緒的框架。
本文連結:李柱明部落格-框架: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-08-21 17:22:18
* @version v1.0
* @copyright Copyright By lizhuming, All Rights Reserved
* @blog https://www.cnblogs.com/lizhuming/
*
**********************************************************
* @LOG 修改日誌:
**********************************************************
*/
#include <stdio.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(struct notifier **notif, notify_func func, void *arg)
{
struct notifier *np;
for (np = *notif; np != 0; np = np->next)
{
if (np->func == func && np->arg == arg)
{
return 0; // already exist
}
}
np = (struct notifier *)os_malloc(sizeof(struct notifier));
if (np == NULL)
{
os_printf("no mem\n");
return -1;
}
np->next = *notif;
np->func = func;
np->arg = arg;
*notif = np;
return 0;
}
/**
* @name add_notifier
* @brief remove a function from the list of things to be called when something happens.
* @param
* @retval
* @author lzm
*/
void remove_notifier(struct notifier **notif, notify_func func, void *arg)
{
struct notifier *np;
for (; (np = *notif) != 0; notif = &np->next)
{
if (np->func == func && np->arg == arg)
{
*notif = np->next;
os_free(np);
break;
}
}
}
/**
* @name notify
* @brief call a set of functions registered with add_notify. (執行該單向連結串列中的所有回撥函式)
* @param
* @retval
* @author lzm
*/
void notify(struct notifier *notif, int type, int val)
{
struct notifier *np;
while ((np = notif) != 0)
{
notif = np->next;
(*np->func)(np->arg, type, val);
}
}
/* demo 放到其它檔案 */
struct notifier *lzm_evt_notifer = NULL;
/**
* @name lzm_register_notifier
* @brief
* @param
* @retval
* @author lzm
*/
int lzm_register_notifier(notify_func func, void *arg)
{
return lzm_add_notifier(&lzm_evt_notifer, func, arg);
}
/**
* @name lzm_remove_notifier
* @brief api
* @param
* @retval
* @author lzm
*/
void lzm_remove_notifier(notify_func func, void *arg)
{
remove_notifier(&lzm_evt_notifer, func, arg);
}
/**
* @name lzm_notify
* @brief api
* @param
* @retval
* @author lzm
*/
void lzm_notify(int type, int val)
{
notify(&lzm_evt_notifer, type, val);
}
介面檔案
/** @file lzm_notifier.h
* @brief 簡要說明
* @details 詳細說明
* @author lzm
* @date 2021-08-21 17:33:06
* @version v1.0
* @copyright Copyright By lizhuming, All Rights Reserved
* @blog https://www.cnblogs.com/lizhuming/
*
**********************************************************
* @LOG 修改日誌:
**********************************************************
*/
#ifndef __lzm_notifier_h__
#define __lzm_notifier_h__
typedef void (*notify_func)(void *, int type, int value);
struct notifier
{
struct notifier *next;
notify_func func;
void *arg;
};
extern struct notifier *lzm_evt_notifer;
int add_notifier(struct notifier **notif, notify_func func, void *arg);
void remove_notifier(struct notifier **notif, notify_func func, void *arg);
void notify(struct notifier *notif, int type, int val);
/* demo 放到其它檔案 */
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);
#endif /* Head define end*/