分时调度协程脚本语言

2023-12-09 00:05:02 +08:00
 monkeyNik

今天的主角是一个分时调度协程的脚本语言——Melang。这篇文章主要介绍 Melang 的协程使用。关于 Melang 的安装,可以参考安装文档

之所以强调分时调度,其实是为了强调 Melang 协程和其他语言协程的差异。在 Lua 、Go 中,当某一个协程运行时,如果不调用某些特定库函数或者 yield 之类的函数,那么当前协程将一直持有 CPU 执行权,也就导致了其他协程或者 I/O 事件或者其他类型事件无法被响应,进而导致整个系统出现运行异常的情况。诚然,经过精密的设计,可以完全避免这类问题。但也会给开发者增加维护和学习成本。而 Melang 的每个协程,都是运行一段时间后被解释器强制中断挂起,让其他协程或者 I/O 事件等得以运行和处理。

在 Melang 中,每一个协程就是一个脚本任务,它可能是文件,也可能只是一段代码片段。每一个协程都有相对独立的运行上下文(也就是相对独立的运行环境),但也允许通过脚本库函数使得多个协程间进行通信。

下面给出两种启用多个协程的方法:

方法 1

//a.m
sys = Import('sys');

while (true) {
  sys.print('a');
}
//b.m
sys = Import('sys');

while (true) {
  sys.print('b');
}

假设我们有这两个协程示例(也是两个文件),它们的功能就是死循环向终端输出ab

我们可以通过如下命令在单个线程内运行这两个协程:

melang a.m b.m

可以看到他们的输出大致如下:

...
a
a
a
a
a
a
a
a
...
b
b
b
b
b
b
b
...
a
a
a
a
a
a
a
a
...

由于 lua 等老牌支持协程的语言实现缘故,可能一些读者会怀疑我在sys.print中加入了强制切换协程的代码,那么可以使用如下示例自行验证一下。

//a.m
while (true){}
//b.m
while (true){}
//c.m
sys = Import('sys')
while (true) {
  sys.print('c');
}
melang a.m b.m c.m

方法 2

使用内置函数Eval拉起协程。

我们首先假设同一路径下的有两个文件名为:a.mb.m。当然,实际使用中,可以放在不同路径下,这里只是为了演示方便。

//a.m
sys = Import('sys');

Eval('b.m');

while (true) {
  sys.print('a');
}
//b.m
sys = Import('sys');

while (true) {
  sys.print('b');
}

然后执行如下命令:

melang a.m

我们可以得到与方法 1 中第一个示例一样的输出。

Eval还有另一种用法,示例如下:

//a.m
sys = Import('sys');

Eval('sys = Import("sys"); while (true) {sys.print("b");}', nil, true);

while (true) {
  sys.print('a');
}

然后执行

melang a.m

依旧可以得到一样的输出效果。

事实上,上述的两种方法都只是对脚本解释器提供的 API 的不同封装。我们也可以自己开发其他的协程启动形式。

感谢阅读!

感兴趣的读者可以访问Github 仓库或者官方文档了解更多内容。

446 次点击
所在节点    编程
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/998855

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX