手上有个FreeRTOS的模拟器是用PThread实现的
引用
评论
// coroutine.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <queue>
#include <tuple>
using namespace std;
struct CoContext;
typedef void (*CoRoutine)(CoContext*);
queue<pair<int, cocontext*>> resumequeue;
struct CoContext {
CoContext(
CoRoutine pfunc, INT_PTR resume1 = 0, INT_PTR resume2 = 0, INT_PTR resume3 = 0,
CoContext* resumecontext = NULL, int resumetick = 1, bool finished = false)
: pfunc(pfunc), resume1(resume1), resume2(resume2), resume3(resume3),
resumecontext(resumecontext), resumetick(resumetick), finished(finished)
{
// 构造函数
}
CoRoutine pfunc;
INT_PTR resume1;
INT_PTR resume2;
INT_PTR resume3;
CoContext *resumecontext;
int resumetick;
bool finished;
};
void pushcontext(int tick, CoContext *ctx)
{
resumequeue.push(pair<int, cocontext*>(tick, ctx));
}
void coroutine1(CoContext *ctx);
int main()
{
CoContext *ctx = new CoContext(coroutine1);
pushcontext(1, ctx);
while (1)
{
if (!resumequeue.empty() && --resumequeue.front().first <= 0) { cocontext *ctx="resumequeue.front().second;" if (ctx->finished)
{
if (ctx->resumecontext)
pushcontext(ctx->resumetick, ctx->resumecontext);
else
delete ctx; // 此处存在问题,见06-01更新说明
}
else
{
ctx->pfunc(ctx);
}
resumequeue.pop();
}
Sleep(1);
}
return 0;
}
////////////////////////////////////////////////////////////
// 两个异步函数
// coroutine1调用coroutine2
// coroutine2返回coroutine1但仍在工作(这里以空等来模拟)
// coroutine1设置coroutine2的恢复点为自己,并等待(返回消息循环)
// coroutine2工作完成,设置finished标志
// 消息循环检测到了finished标志,恢复coroutine1的状态
// coroutine1恢复以后删除coroutine2的状态
// coroutine1完成并返回消息循环
// 消息循环检测到了finished标志,由于恢复点为空,将删除它的状态
void coroutine2(CoContext *ctx)
{
if (ctx->resume1 == 1) goto resume1; // 跳到恢复点
// 空等待1000ms
printf("just suspend 200 ticks\n");
ctx->resume1 = 1;
return pushcontext(200, ctx);
resume1:
printf("after suspend 200 ticks\n");
// 处理完成并返回
printf("set finished\n");
ctx->finished = true;
return pushcontext(1, ctx);
}
void coroutine1(CoContext *ctx)
{
if (ctx->resume1 == 1) goto resume1; // 跳到恢复点
// 调用异步函数
printf("before calling\n");
CoContext *ctx2 = new CoContext(coroutine2);
coroutine2(ctx2);
printf("after calling\n");
// 等待await
printf("before awaiting\n");
ctx2->resumecontext = ctx;
ctx2->resumetick = 1;
ctx->resume1 = 1;
ctx->resume2 = (INT_PTR)ctx2;
return;
resume1:
delete (CoContext*)ctx->resume2;
printf("after awaiting\n");
// 处理完成并返回
printf("set finished\n");
ctx->finished = true;
return pushcontext(1, ctx);
}</=></int,></pair<int,></tuple></queue></windows.h></stdio.h>
// coroutine.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <queue>
using namespace std;
struct CoContext;
typedef void (*CoRoutine)(CoContext*);
queue<pair<int, cocontext*>> resumequeue;
struct CoContext {
CoContext(
CoRoutine pfunc, INT_PTR resume1 = 0, INT_PTR resume2 = 0, INT_PTR resume3 = 0,
CoContext* resumecontext = NULL, int resumetick = 1, bool finished = false, bool abandoned = false)
: pfunc(pfunc), resume1(resume1), resume2(resume2), resume3(resume3),
resumecontext(resumecontext), resumetick(resumetick), finished(finished), abandoned(abandoned)
{
// 构造函数
}
CoRoutine pfunc;
INT_PTR resume1;
INT_PTR resume2;
INT_PTR resume3;
CoContext *resumecontext;
int resumetick;
bool finished;
bool abandoned;
};
void pushcontext(int tick, CoContext *ctx)
{
resumequeue.push(pair<int, cocontext*>(tick, ctx));
}
void coroutine1(CoContext *ctx);
int main()
{
CoContext *ctx = new CoContext(coroutine1);
ctx->abandoned = true;
pushcontext(1, ctx);
while (1)
{
if (!resumequeue.empty() && --resumequeue.front().first <= 0) { cocontext *ctx="resumequeue.front().second;" if (ctx->finished)
{
if (ctx->resumecontext)
pushcontext(ctx->resumetick, ctx->resumecontext);
else if (ctx->abandoned)
delete ctx;
else
pushcontext(1, ctx);
}
else
{
ctx->pfunc(ctx);
}
resumequeue.pop();
}
Sleep(1);
}
return 0;
}
////////////////////////////////////////////////////////////
// 两个异步函数
// coroutine1调用coroutine2
// coroutine2返回coroutine1但仍在工作(这里以空等来模拟)
// coroutine1设置coroutine2的恢复点为自己,并等待(返回消息循环)
// coroutine2工作完成,设置finished标志
// 消息循环检测到了finished标志,恢复coroutine1的状态
// coroutine1恢复以后删除coroutine2的状态
// coroutine1完成并返回消息循环
// 消息循环检测到了finished标志,由于abandoned=true,将删除它的状态
void coroutine2(CoContext *ctx)
{
if (ctx->resume1 == 1) goto resume1; // 跳到恢复点
// 空等待1000ms
printf("just suspend 200 ticks\n");
ctx->resume1 = 1;
return pushcontext(200, ctx);
resume1:
printf("after suspend 200 ticks\n");
// 处理完成并返回
printf("set finished\n");
ctx->finished = true;
return pushcontext(1, ctx);
}
void coroutine1(CoContext *ctx)
{
if (ctx->resume1 == 1) goto resume1; // 跳到恢复点
// 调用异步函数
printf("before calling\n");
CoContext *ctx2 = new CoContext(coroutine2);
coroutine2(ctx2);
printf("after calling\n");
// 等待await
printf("before awaiting\n");
ctx2->resumecontext = ctx;
ctx2->resumetick = 1;
ctx->resume1 = 1;
ctx->resume2 = (INT_PTR)ctx2;
return;
resume1:
delete (CoContext*)ctx->resume2;
printf("after awaiting\n");
// 处理完成并返回
printf("set finished\n");
ctx->finished = true;
return pushcontext(1, ctx);
}</=></int,></pair<int,></queue></windows.h></stdio.h>引用 金星凌日:实际上,javascript中的基于闭包的异步编程重新回到了面条式编程,lua或者c# 5.0或es6的async/await(coroutine)机制对异步编程最大的贡献是实现了结构化异步编程。
感觉这样的异步比JavaScript中的异步更不自然。
如果用Lua,可以让异步代码形式上看起来是同步的,但实际上是异步执行。这样的代码人更容易理解。
引用 acmilan:我记得类似的东西在Scheme里也出现过。
实际上,javascript中的基于闭包的异步编程重新回到了面条式编程,lua或者c# 5.0或es6的async/await(coroutine)机制对异步编程最大的贡献是实现了结构化异步编程。
引用 amo:这个只是一个原型程序(演示程序),并不是实用程序。。。(实用需要语法糖或宏的支持)
不友好……
建议搜索“protothread”了解一下。这是uip带的。uip和lwip的作者出品
引用 acmilan:你说的“并行”和“异步”,实际上是同一个玩意……
这个只是一个原型程序(演示程序),并不是实用程序。。。(实用需要语法糖或宏的支持)
protothread主要是为了并行编程而设计的,并没有针对异步串行编程设计的队列和上下文管理。。。
对异步串行编程友好的语言,需要具有async/...
引用 amo:no。。。虽然都转换为状态机,但是很显然它们的理念是不同的,所以并不是同一个玩意,不能随意混淆。。。
你说的“并行”和“异步”,实际上是同一个玩意……
编译器的实现,也是转为状态机。但是在C/C++里protothread的兼容性更好,天生就是跨平台的,同一份代码在单片机、windows、linux……上都能跑,不管用什么C/C++编译器...
异步和并行肯定是同一个玩意儿。穿了一个马甲而已, 异步肯定是并行的,同一个时间在执行不同的流程,虽然流程不同,但同属于一个程序、一个逻辑。谁说并行一定是多个核心执行同一款代码?