C语言——特殊状态机

一、前言

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

二、举例 

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

#include <stdio.h>

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

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

 三、优化代码

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

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

简单优化一下:

#include <stdio.h>

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\n");
    }
    else
    {
        printf("obsolete\n");
    }
    // 触发
    condition = 0;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass\n");
    }
    else
    {
        printf("obsolete\n");
    }
    // 等待
    condition = 1;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass\n");
    }
    else
    {
        printf("obsolete\n");
    }
    // 触发
    condition = 0;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass\n");
    }
    else
    {
        printf("obsolete\n");
    }

    while (1)
    {
    }
}

四、封装 

#include <stdio.h>

#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\n");
    }
    else
    {
        printf("obsolete\n");
    }
    // 触发
    condition = 0;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass\n");
    }
    else
    {
        printf("obsolete\n");
    }
    // 等待
    condition = 1;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass\n");
    }
    else
    {
        printf("obsolete\n");
    }
    // 触发
    condition = 0;
    function_init();
    if (!function_handle(condition))
    {
        printf("pass\n");
    }
    else
    {
        printf("obsolete\n");
    }
    while (1)
    {
    }
}

五、源码

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

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>

#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\n", 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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值