【框架】一種通知到多執行緒框架

李柱明發表於2021-08-30

前言

本文記錄通過回撥函式通知到多執行緒的框架。
本文連結:李柱明部落格-框架: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*/

相關文章