在存在多个协程的环境中,实现优先级是否合理?

我正在阅读一些 Lua 书籍,考虑将一些遗留的(并且糟糕编写的) C 代码迁移到 Lua 和 C 的混合环境中。

然而,这个遗留代码使用线程来处理一些关键任务(基本上是音频/视频流式处理),同时还有一些需要关注的简单任务(用户接口)。根据我所读的,Lua 并不直接支持线程,而且它提倡使用协程。

像这样的情况迁移到基于协程的环境中合理吗?在我的脑海中,我可以想象一个调度程序,它始终会在每次尝试恢复一个不太重要的协程之前,首先尝试恢复高优先级的协程。由于我对这个主题没有经验,所以我在这里提出这个问题。

编辑

Nicol Bolas 要求提供更多细节。

这是一个实时应用程序。我不能承受处理一些事件的大延迟,比如一帧新视频准备好被处理。以前的 C 程序使用线程和回调来处理这个问题。例如,在发生新帧的情况下,调用回调并准备数据进行处理(回调作为生产者,视频线程作为消费者)。

我还没有想到怎么处理回调(也许我会保留它们与 C 并使用一些互斥锁来更新 Lua 代码的数据),但我的疑问是,使用上述工具设置这种类型的环境是否适用于这种问题,是否有人有例子或故事想要分享一下。

点赞
用户13663
用户13663

将下面翻译成中文并且保留原本的 markdown 格式

There's no reason you can't try this. The game is to create an appropriate scheduler, and to ensure that none of your routines take too much time before they yield.

How difficult this will be depends on your code, but the scheduler is likely to be pretty simple -- via priorities or simple timers (if last time important_routine was run is > N ms, then run important_routine).

You have some advantages with yield, it certainly makes synchronization easy.

Simply put, you should proof it out and see if it's effective enough for you. Play with it a bit and you should know reasonably quickly if this will actually work out for you or not, from the sounds of it, your scheduler is likely not really sophisticated. There's no reason to make it a general purpose one, keep it simple and dedicated to the tasks you're doing, then you round robin the "generic ones", or pull some random scheduler out of an operating systems text book.

你完全可以尝试这个方法。游戏的关键是创建一个适当的调度器,并确保在程序执行 yield 前,没有任何一个程序占用过多的时间。

调度器的难度取决于你的代码,但调度器可能相当简单 - 使用优先级或简单的定时器(如果重要程序上次运行时间 > N 毫秒,则运行重要程序)。

yield 为你带来了一些优势,这使得同步过程更加容易。

简单来说,你应该对它进行测试,看看它是否对你有效。试玩一下,你很快就会知道这个方法是否适合你,从声音中可以听出,你的调度程序可能并不是非常复杂。没有必要把它变成通用的调度程序,保持它的简单和专注于你正在处理的任务,然后循环执行“通用程序”,或从操作系统教材中随意选择一些随机调度程序。

2012-09-07 04:25:03
用户1442917
用户1442917

你可能是可以做到这一点的;就我所知,你最大的挑战在于决定你可以放弃的最小时间块,并如何保证这个时间块不会超过限制。

举个例子,假设你的流媒体可以容忍多达10毫秒的延迟。这意味着你的UI操作必须分成不超过10毫秒的块。假如你恢复了UI coroutine来搜索文件,但需要读取的文件很大,读取时间超过了10毫秒怎么办?直到UI coroutine将控制权传回给调度器,调度器才会恢复你的流媒体coroutine。这意味着你需要非常小心地考虑你的UI可以执行的所有操作,以及如何保证它们都遵守你为它们设置的时间限制。

在抢占式多任务处理中,调度程序会处理这个问题(但它也有自己的缺点),但在coroutine的情况下,你的UI逻辑需要处理这个问题。有一些Lua库具有类似的逻辑(例如,使用超时的copas库可以提供你所需的一些解决方案)。

比较回调和coroutine,我开始越来越喜欢coroutine的方法。它们在能做的事情上可能是等效的,但基于coroutine的代码比基于回调的代码更容易阅读(在我看来)。

2012-09-07 05:31:55