:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨
:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】
:文章若有幸对你有帮助,可点赞 收藏 ⭐不迷路
:内容若有错误,敬请留言 指正!原创文,转载请注明出处
协程,英文Coroutines,是一种比线程更加轻量级的存在
1、协程就是一个可以在某个地方挂起的特殊函数,并且可以重新在挂起处继续运行。
2、一个线程内的多个协程的运行是串行的。
3、如果有多核CPU的话,多个进程或一个进程内的多个线程是可以并行运行的,但是一个线程内的多个协程却绝对串行的,无论有多少个CPU(核)。
4、一个线程内的多个协程是串行执行的,不能利用多核,所以,显然,协程不适合计算密集型的场景。协程适合I/O 阻塞型。
ProtoThread是一个极简的C语言协程库,由5个简单的.h文件构成。ProtoThread主要是利用switch case内嵌循环的特殊语法来实现的。因为ProtoThread完全是利用C语言的语法特性,所以ProtoThread可以适用所有C/C++项目。我们创建并使用协程都要用到这个协程库,而这个库主要使用宏去定义协程。其次我们在定义的时候都使用PT来表示协程的意思。
.h文件介绍:
lc.h :local continuation,本地程序。以标准C的switch结构实现Protothreads系统。
pt.h :Protothreads的接口,必须包含此头文件。
pt-sem.h :附加的信号量操作的支持,不需要的话则不必包含他在pt.h中包含所有实现Protothreads的宏和变量结构的定义。
LC是local continuation,是Protothread机制的底层支持,用来保存进程运行状态的地方,其实就是保存进程实体函数上次阻塞的位置。
协程宏
协程宏是一种利用宏定义来简化协程的创建和管理的技术。在C语言中,可以使用宏来实现协程的简单调度。通过定义一组宏,可以将协程的创建、切换、暂停和恢复等操作以类似于语言级别的方式进行编写和使用。
这段代码是为一种协程实现定义了4个常量。
以下是对这些常量的解释:
#define PT_WAITING 0
#define PT_YIELDED 1
#define PT_EXITED 2
#define PT_ENDED 3
PT_WAITING
的值为0
,表示协程处于等待状态。PT_YIELDED
的值为1
,表示协程已经暂停执行,并且可以被恢复继续执行。PT_EXITED
的值为2
,表示协程已经完成执行并退出。PT_ENDED
的值为3
,表示协程已经结束(可能是正常结束或异常结束)。
struct pt {
lc_t lc;
unsigned short HeapSize;
void *pHeap;
};
这段代码定义了一个名为
pt
的结构体,其中包含了以下成员变量:
lc_t lc
:一个类型为lc_t
的变量,可能是用于保存协程执行状态的上下文或相关信息。unsigned short HeapSize
:一个无符号短整型变量,表示堆大小。void *pHeap
:一个指向void
类型的指针,指向一个堆内存区域。这个结构体的目的是在协程实现中保存和管理相关的数据。
lc_t
可能是一个类型别名,用于表示协程的执行状态,例如使用汇编语言或特定库函数对协程进行处理。
HeapSize
和pHeap
成员变量用于处理堆内存的分配和管理,可能在协程执行过程中需要动态分配一些内存。
#define LC_INIT(s) s = 0;
#define PT_INIT(pt) LC_INIT((pt)->lc)
这是一个宏定义,用于初始化一个名为
pt
的指针。
它调用了另一个宏LC_INIT
,并将pt
指向的对象的lc
成员作为参数传递给LC_INIT
。
协程的开始
#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
这是一个宏定义,用于开始一个结构体或类的定义。它首先将全局变量
PT_YIELD_FLAG
设置为1,然后调用LC_RESUME
函数,将pt
指向的对象的lc
成员作为参数传递给该函数。
协程的退出
#define PT_EXIT(pt) \
do { \
PT_INIT(pt); \
return PT_EXITED; \
} while(0)
协程的结束
#define LC_END(s)
#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
PT_INIT(pt); return PT_ENDED; }
这段代码是一个宏定义,用于结束一个名为
pt
的指针。它首先调用了另一个宏LC_END
,将pt
指向的对象的lc
成员作为参数传递给LC_END
。然后,它将全局变量PT_YIELD_FLAG
设置为0,表示不再产生yield。最后,它再次调用PT_INIT
宏,初始化pt
指针,并返回一个名为PT_ENDED
的标志。