• 【框架】一种通知到多线程框架


    前言

    本文记录通过回调函数通知到多线程的框架。
    本文链接:李柱明博客-框架: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
    ");
            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*/
    
    
  • 相关阅读:
    json
    ajax
    oracle 分页查询
    NuGet使用
    【EF】Entity Framework使用
    【mssql】增删改查笔记
    【mysql】知识点
    【angularJS】学习笔记
    C# Ninject使用
    【CSS】Table样式
  • 原文地址:https://www.cnblogs.com/lizhuming/p/15205560.html
Copyright © 2020-2023  润新知