protothread协程库实现非阻塞延时(无操作系统)
协程库官网下载
参考连接
https://blog.csdn.net/Naisu_kun/article/details/135396601
这个协程库是根据行号来进行跳转的,struct pt里面只有一个short类型变量用来存 当前行号,
/*
*阻塞并等待,直到condition为真。
*这个宏会阻塞原线程,直到满足指定的条件
*/
一个指向原线程控制结构的指针。
#define PT_WAIT_UNTIL(pt, condition)PT_INIT(pt)就是把这个行号清0
PT_END(pt);//线程结束
PT_INIT和PT_END要成对出现,因为他们是宏函数,PT_INIT里面只有一个 {,PT_END有一个},
只需要下面三个头文件即可实现非阻塞延时
具体代码如下,加sleep 1 是为了观察实验现象,项目里不加延时。
#include <stdio.h>
#include <stdlib.h>
#include "pt.h"
#include <time.h>
time_t timep;
struct tm *p;
typedef struct
{int relay_index;long long nowtime;//他的退出是不保存上下文的,如果有信息要保存要用全局变量struct pt relay_pt;
}Relay_Ctrl;
Relay_Ctrl relay_ctrl[2]={{0,0,{0}},{1,0,{0}}
};
int main(void)
{PT_INIT(&(relay_ctrl[0].relay_pt));//线程1初始化PT_INIT(&(relay_ctrl[1].relay_pt));//线程2初始化while(1){protothread(&relay_ctrl[0]);//执行线程0sleep(1);//延时1sprotothread(&relay_ctrl[1]);//执行线程1}printf("this is end\n");
}int protothread(Relay_Ctrl *relayCtrl)
{PT_BEGIN(&(relayCtrl->relay_pt));//线程开始while(1){relayCtrl->nowtime = time(&timep);PT_WAIT_UNTIL(&(relayCtrl->relay_pt), (time(&timep)-relayCtrl->nowtime>=2));//如果时间满2秒继续执行,否则记录运行点并退出线程1time(&timep); // 获取当前时间的秒数p = gmtime(&timep); // 将秒数转换为 tm 结构体printf("pt_%d_1过后当前时间:%d\n",relayCtrl->relay_index,p->tm_sec);relayCtrl->nowtime = time(&timep);PT_WAIT_UNTIL(&(relayCtrl->relay_pt), (time(&timep)-relayCtrl->nowtime>=5));//如果时间满5秒继续执行,否则记录运行点并退出线程1time(&timep); // 获取当前时间的秒数p = gmtime(&timep); // 将秒数转换为 tm 结构体printf("pt_%d_2过后当前时间:%d\n",relayCtrl->relay_index,p->tm_sec);}PT_END(&(relayCtrl->relay_pt));//线程结束
}
注意避坑
不能用switch,不要用局部变量,因为他是不保存上下文的。