【框架】一種通知到多線程框架


前言

本文記錄通過回調函數通知到多線程的框架。
本文鏈接:李柱明博客-框架: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(&notifier_ctx_ptr->lock);
    
    for(np = notifier_ctx_ptr->notif; np != NULL; np = np->next) 
    {
        if(np->func == func && np->arg == arg) 
        {
            pthread_mutex_unlock(&notifier_ctx_ptr->lock);
            return 0;        // already exist
        }
    }

    np = (notifier_t *)malloc(sizeof(notifier_t));
    if (np == NULL) 
    {
        pthread_mutex_unlock(&notifier_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(&notifier_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(&notifier_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(&notifier_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(&notifier_ctx_ptr->lock);

    np = notifier_ctx_ptr->notif;
    while (np != NULL) 
    {
        (*np->func)(np->arg, type, val);
        np = np->next;
    }

    pthread_mutex_unlock(&notifier_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(&notifier_ctx_ptr->lock, NULL);

    pthread_mutex_lock(&notifier_ctx_ptr->lock);

    notifier_ctx_ptr->notif = NULL;
    
    pthread_mutex_unlock(&notifier_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(&notifier_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(&notifier_ctx_ptr->lock);

    pthread_mutex_destroy(&notifier_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*/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM