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

前言

本文记录通过回调函数通知到多线程的框架。
本文链接:李柱明博客-框架: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*/

原文地址:https://www.cnblogs.com/lizhuming/p/15205560.html