双链表小试牛刀-模块代码-源码list_for_each有bug需要do-while缓解尴尬

 

#include "gbaselist.h"



static uint8_t	           SoncetimerTaskId = 0;   //表示每个节点的标号 可以统计个数 以及 根据ID查找以小博大
static node_oncetime_type *Soncetimerhead = NULL;  //链表的头结点


//遍历链表 周期loop执行
void once_timer_list_loop( void )
{
    struct list_head *pos;
	node_oncetime_type *priv;
	if( Soncetimerhead == NULL) return;
#if 0
    list_for_each(pos,  &Soncetimerhead->list)
//  for (pos = (head)->next; pos != (head); pos = pos->next)
    {

        priv = list_entry(pos, node_oncetime_type, list);
        if( priv->start)
        {
            if( ++priv->cnt >= priv->time_out)
            {
                priv->cnt = 0;
                if(priv->fun != NULL)	priv->fun();
            }
        }
    }
#else
    pos =  (&Soncetimerhead->list)->next;
    do
    {
        priv = list_entry(pos, node_oncetime_type, list);
        if( priv->start)
        {
            if( ++priv->cnt >= priv->time_out)
            {
                priv->cnt = 0;
                if(priv->fun != NULL)	priv->fun();
            }
        }
    pos = pos->next;
    }while( pos !=  (&Soncetimerhead->list));
#endif

}


//关闭节点 《并没有链表移除 而是用标记位 优点:方便简单 缺点:内存无法释放》
uint8_t once_timer_stop(uint8_t handle)
{
    struct list_head *pos, *next;//为了安全迭代 搞2个进去 其实list_for_each_safe主要是第三个头
	node_oncetime_type *priv;
    printf("==== find node(handle:%d) ====\n",handle);
    list_for_each_safe(pos, next, &Soncetimerhead->list)
    {
        priv = list_entry(pos, node_oncetime_type, list);
        if(priv->handle == handle)
        {
            priv->start = false;
            priv->cnt = 0;
            return true;
        }
    }
    return false;
}
//开启节点 
uint8_t once_timer_start(uint8_t handle)
{
    struct list_head *pos, *next;//为了安全迭代 搞2个进去 其实list_for_each_safe主要是第三个头
	node_oncetime_type *priv;
    printf("==== find node(handle:%d) ====\n",handle);
    list_for_each_safe(pos, next, &Soncetimerhead->list)
    {
        priv = list_entry(pos, node_oncetime_type, list);
        if(priv->handle == handle)
        {
            priv->start = true;
            priv->cnt = 0;
            return true;
        }
    }
    return false;
}

//一个节点添加到链表 返回它的ID
uint8_t once_timer_register( node_oncetime_type* node, uint32_t time_out ,uint8_t start, func_call_back call_back)
{
	node_oncetime_type *this;

	this = node;//可以思考用malloc实现  目前这里和button一样我是自带内存

	this->cnt = 0;//实际计数值
	this->start = start;//开关
	this->handle = ++SoncetimerTaskId;//在链表中的ID
	this->time_out = time_out;//超时计数值
	this->fun = call_back;//节点逻辑函数

	if( Soncetimerhead == NULL)
	{
		Soncetimerhead = this;//第一次 实例化head
        INIT_LIST_HEAD(&node->list);
	    printf("__new oncetimer handle=%d\r\n",SoncetimerTaskId);
	}
	else
	{
        list_add_tail(&(node->list), &(Soncetimerhead->list));
	    printf("new oncetimer handle=%d\r\n",SoncetimerTaskId);
	}    


	return (this->handle);
}


once_time_ops_type   timer =
{
    .creat = once_timer_register,
    .stop  = once_timer_stop , 
    .start = once_timer_start,
};





#ifndef _GBASELIST_H_
#define _GBASELIST_H_

#include 
#include 
#include 
#include 
#include 
#include //offsetof
#include "glist.h" 

typedef void    (*func_call_back)(void);

/*****************模式1 周期性执行一次函数类似[000000000001][000000000001]这样子*************/
//节点的结构体
//因为我放弃了malloc只能参数自己携带内存 所以也对外提供节点的结构体
typedef struct  
{
	uint8_t     handle;//ID
	
	uint8_t     start;//开关
	
	uint32_t    cnt;//这个是实际计数值 每次+1 直到==下面设置值 就执行fun
	uint32_t    time_out;//这个是约定值 溢出值
	
	void        (*fun)(void);
	struct list_head 	list; 
}node_oncetime_type;

//操作 节点结构体的结构体
typedef struct
{
    uint8_t (*creat) (  node_oncetime_type* node ,uint32_t time_out ,uint8_t start, func_call_back call_back);
    uint8_t (*stop)  (  uint8_t  handle);
    uint8_t (*start) (  uint8_t  handle);
}once_time_ops_type;

//对外提供的句柄
extern once_time_ops_type   timer;

//周期轮训业务 轮训链表的函数
void once_timer_list_loop( void );



其中有一个diwhile 缓解尴尬!!

当双链表只有一个节点的时候 源码的循环不行!!!

需要使用dowhile!!

你可能感兴趣的:(双链表小试牛刀-模块代码-源码list_for_each有bug需要do-while缓解尴尬)