如何在iOS上实现协程

3
我正在将一个C++项目移植到iOS上,以在iPhone和iPad上使用。这个项目广泛使用了Boost.Coroutine库。Boost.Coroutine没有针对iPhone的ARMv6 / ARMv7指令集实现。
  • 是否有其他协程库可以在iOS上运行?

  • 如果没有,是否有可能在ARM上编写协程行为?我可以看到几种潜在的方法:

    • 直接编写汇编指令来执行堆栈操作。我对汇编不是很熟悉,而且我担心ARM架构可能不包括复制和粘贴堆栈所需的指令,或者手动移动堆栈指针。
    • 使用类似于pthread或Win32纤程的东西编写协程。我不确定是否有类似于此可用于iOS的东西。
    • 在线程之上实现协程,甚至是Boost.Coroutine本身。这似乎最有可能起作用,但肯定会有性能缺陷。

注意:Unity在iOS上支持C#中的协程;我不确定这是否仅限于典型协程行为的较小子集。如果没有,这是否意味着Unity有解决方案?


1
协程通常是一个坏主意——穷人的多任务处理。而且,你可以使用iOS调度队列来实现大部分相同的功能。(请记住,搞乱调用堆栈非常危险。) - Hot Licks
2
@Hot Licks 协程非常有用,以至于人们希望在语言中拥有它们(或者像continuations这样更强大的功能),而且它们不是穷人的多任务处理。以单线程生产者/消费者为例 - 使用协程可以自然地表达,而相同的多线程版本将需要锁。状态机是另一个常见的例子。如果协程是个坏主意,为什么许多现代语言都内置了对它们的支持?为什么人们会为没有此类支持的语言(从C到C#)实现它们?调度队列很好,但在这里无关紧要。 - hoha
一些语言,例如实现“continuations”的语言需要类似于协程的东西,但大多数语言不需要。至于生产者/消费者,让我向您保证,在现代操作系统上,协程版本会比多线程版本更复杂(几乎肯定需要锁来防止来自操作系统的破坏性干扰)。我曾经开始在一个裸露的PALM IV微控制器上实现协程方案,但最终发现非抢占式任务调度方案更加简洁。这是针对IBM 5100的经典生产者/消费者磁带复制实用程序。 - Hot Licks
@Hot Licks 我的主要观点是,在许多情况下,使用协程会更好(当它们存在时)。即使多线程实现更高效(看来你对此更了解),协程仍然是语义上不同的特性 - 在大多数情况下,我们应该先考虑可读性,而后再考虑性能。 - hoha
1
@Tommy 在这个项目中,协程主要用于RPC库。为了从原始项目中获取持续的修复和改进,我希望将我的解决方案尽可能地保持与源实现相似。也就是说,如果我必须重写他们的RPC库以不使用协程,我会这样做,但我想彻底调查在iOS上实现协程的选项。 - JMac
显示剩余10条评论
2个回答

5
您几乎肯定不想编写汇编指令来执行堆栈操作。iOS已经使用ARM指令集的第三个版本,从ARMv6到ARMv7再到ARMv7s。从iPhone 5开始,苹果公司进一步添加了人为障碍,即您不能提交既支持ARMv6分叉又支持完整iPhone 5屏幕的应用程序。我相信苹果公司的动机是确保在未来某个时候可以过渡到没有ARMv6兼容模式的处理器,但对于我们开发人员来说,这显然意味着不要过度依赖特定的指令集。
那就只剩下线程了。iOS拥有一套完整的、经过充分开发的线程机制,而pthread则用于公开相关子集。Grand Central Dispatch往往是现在使用的正常解决方案,以确保不同的任务可以同时进行,因此吞噬了大部分互联网文档,但低级别的解决方案仍然存在。
明显的微不足道的例子,使用NSConditionLock
- (void)methodOnThread1
{
    while(1)
    {
        [conditionLock lockWhenCondition:kMoreInputAvailable];

        // process whatever is currently in the common access pool

        [conditionLock unlockWithCondition:kWaitingForInput];
    }
}

- (void)methodOnThread2
{
    while(1)
    {
         // do whatever is necessary to produce more input,
         // creating it locally and taking as long as it takes


        [conditionLock lockWhenCondition:kWaitingForInput];

        // push input to common access pool, by whatever means

        [conditionLock unlockWithCondition:kMoreInputAvailable];
    }
}

4
boost.coroutine(来自Oliver Kowalke;上个月由boost社区进行了审核)使用支持ARMv6(ARM Cortex Ax)的boost.context。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接