聊聊C语言|特殊状态机

描述

| 核心机制

状态机是非常常用的框架之一,本质就是通过记录状态值来执行对应动作,但是有个问题就是每个对应的状态值都有对应的动作,如果碰到需要等待信号量再触发的情况下需要特定处理,有没更好的方法处理这种情况呢,答案很多是有的。要解决这需求就要保证代码退出时和下次进入时的位置是不变的,怎么实现呢?

实现这个需求的方式有很多,这里就使用纯C来实现:

 

#include 

int function(void)
{
    static int state;
    switch (state)
    {
    case 0:
        do
        {
            printf("state:%d
", state);
            state = 1;
            return 0;
        case 1:;
            printf("state:%d
", state);
        } while (0);
    }
}

int main()
{
    function(); // 输出state:0
    function(); // 输出state:1
    function(); // 输出state:1
    while (1)
    {
    }
}

 

这里还是采用状态机来实现,由于状态值没有发生改变,函数调用时触发的动作不变,这就保证了函数退出时和再次进入的“入口”相同。

| 优化代码

在介绍优化前,先介绍一下C相关的宏:

 

int main()  
{  
    printf("%d
",__LINE__);//显示所在行号  
    printf("%s
",__func__);//显示所在函数  
    printf("%s
",__TIME__);//显示当前时间  
    printf("%s
",__DATE__);//显示当前日期  
    printf("%s
",__FILE__);//显示所处文件名,在源代码中插入当前源代码文件名  
    printf("%d
",__STDC__);//编译器遵循ANSI C标准时该标识被赋值为1;  
    return 0;  
}

 

简单优化一下:

 

#include 

int state = 0;

void function_init(void)
{
    state = 0;
}

int function_handle(int condition)
{
    switch (state)
    {
    case 0:
        do
        {
            state = __LINE__;
        case __LINE__:
            if (!condition)
                return 0;
            else
                return 1;
        } while (0);
    }
}

int main()
{
    // 等待
    int condition = 1;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass
");
    }
    else
    {
        printf("obsolete
");
    }
    // 触发
    condition = 0;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass
");
    }
    else
    {
        printf("obsolete
");
    }
    // 等待
    condition = 1;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass
");
    }
    else
    {
        printf("obsolete
");
    }
    // 触发
    condition = 0;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass
");
    }
    else
    {
        printf("obsolete
");
    }

    while (1)
    {
    }
}

 

简单封装一下:

 

#include 

#define Begin()    
    switch (state) 
    {              
    case 0:

#define WAIT(condition)   
    do                    
    {                     
        state = __LINE__; 
    case __LINE__:        
        if (!condition)   
            return 0;     
        else              
            return 1;     
    } while (0)

#define End() }

int state = 0;

void function_init(void)
{
    state = 0;
}

int function_handle(int condition)
{
    Begin();
    WAIT(condition);
    End();
}

int main()
{
    // 等待
    int condition = 1;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass
");
    }
    else
    {
        printf("obsolete
");
    }
    // 触发
    condition = 0;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass
");
    }
    else
    {
        printf("obsolete
");
    }
    // 等待
    condition = 1;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass
");
    }
    else
    {
        printf("obsolete
");
    }
    // 触发
    condition = 0;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass
");
    }
    else
    {
        printf("obsolete
");
    }
    while (1)
    {
    }
}

 

| 最后优化

源码:

 

#include 
#include 
#include 
#include 

#define PT_BEGIN()     
    switch (pt->state) 
    {                  
    case 0:

#define PT_END()   
    pt->state = 0; 
    return 0;      
    }

#define PT_WAIT_UNTIL(condition) 
    do                           
    {                            
        pt->state = __LINE__;    
    case __LINE__:               
        if (!(condition))        
            return 0;            
    } while (0)

typedef struct
{
    uint8_t state;
} pt_t;

void pt_init(pt_t *pt)
{
    pt->state = 0;
}

bool pt_run(pt_t *pt)
{
    return pt->state != 0;
}

int thread_fun(pt_t *pt)
{
    static uint32_t counter = 0;

    PT_BEGIN();

    while (1)
    {
        printf("counter = %lu
", counter++);
        PT_WAIT_UNTIL(counter % 10 == 0);
    }

    PT_END();
}

int main()
{
    pt_t pt_a;
    pt_t pt_b;
    pt_init(&pt_a);
    pt_init(&pt_b);
    while (true)
    {
        if (!pt_run(&pt_a))
        {
            thread_fun(&pt_a);
        }
        if (!pt_run(&pt_b))
        {
            thread_fun(&pt_b);
        }
    }

    return 0;
}

 

最后就完成了一个简单的线程,纯C编写非常方便移植和改写!




审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分