V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
monkeyNik
V2EX  ›  编程

分时调度协程脚本语言

  •  
  •   monkeyNik · Dec 9, 2023 · 873 views
    This topic created in 870 days ago, the information mentioned may be changed or developed.

    今天的主角是一个分时调度协程的脚本语言——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 仓库或者官方文档了解更多内容。

    No Comments Yet
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3581 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 11:47 · PVG 19:47 · LAX 04:47 · JFK 07:47
    ♥ Do have faith in what you're doing.