手上有个FreeRTOS的模拟器是用PThread实现的
<code class="lang-cpp">// 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></code>
<code class="lang-cpp">// 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></code>
[修改于 8年7个月前 - 2016/06/01 17:43:42]
引用 金星凌日:实际上,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++编译器...
异步和并行肯定是同一个玩意儿。穿了一个马甲而已, 异步肯定是并行的,同一个时间在执行不同的流程,虽然流程不同,但同属于一个程序、一个逻辑。谁说并行一定是多个核心执行同一款代码?
时段 | 个数 |
---|---|
{{f.startingTime}}点 - {{f.endTime}}点 | {{f.fileCount}} |
200字以内,仅用于支线交流,主线讨论请采用回复功能。