3
votes

I am porting a C++ project to iOS for use on iPhone and iPad. This project uses the Boost.Coroutine library extensively. Boost.Coroutine does not have an implementation for the iPhone's ARMv6/ARMv7 instruction set.

  • Are there other coroutine libraries that can run on iOS?

  • If not, is it possible to write coroutine behavior on ARM? I can see a few potential ways to do this:

    • Write assembly instructions directly to perform the stack manipulation. I am not very well versed in assembly, and I'm worried that the ARM architecture may not include the instructions necessary to copy & paste the stack, or to manually move the stack pointer.
    • Write coroutines using something similar to pthreads, or Win32 fibers. I'm not sure if there's something like this that could be used on iOS.
    • Implement coroutines, perhaps even Boost.Coroutine itself, on top of threads. This seems the most likely to work, but would definitely have performance drawbacks.

Note: Unity supports coroutines in C# on iOS; I'm not sure if this is limited to a smaller subset of typical coroutine behavior. If not, does this mean Unity has a solution?

2
Can you say anything about the specific pattern that you want coroutines for? It would be helpful, above and beyond a bare answer, to be able to say something like 'the reason it's difficult to do Y is that the normal pattern is X'. - Tommy
Coroutines are generally a bad idea -- poor man's multitasking. And you can accomplish most of the same functionality using iOS dispatch queues. (Keep in mind that it's very dangerous to muck with the call stack.) - Hot Licks
@Hot Licks Coroutines are useful enough to want them (or more powerful feature like continuations) in a language, and they are not a poor man's multitasking. Take a single-thread producer/consumer - it can be expressed naturally with coroutines, multithreaded version of the same will require locks. State machines are other common example. If coroutines are bad idea why many modern languages have a built-in support for them? Why people implement them for languages without such support (from C to C#)? Dispatch queues are nice but irrelevant here. - hoha
Some languages, such as those that implement "continuations" need something similar to coroutines, but most languages do not. As to producer/consumer, let me assure you that, on a modern operating system, the coroutine version will be much more complex than the multithreaded version (and will almost certainly require locks to prevent destructive interference from the OS). I once started out to implement a coroutine scheme on a bare PALM IV micro, but ended up discovering that a non-preemptive tasking scheme was cleaner. This was a classical producer/consumer tape copy utility for IBM 5100. - Hot Licks
@Tommy Coroutines are primarily used in this project for the RPC library. In the interest of pulling ongoing fixes and improvements from the original project, I'd like to keep my solution as similar as possible to the source implementation. i.e. if I must rewrite their RPC library to not use coroutines I will, but I'd like to exhaustively investigate the options for implementing coroutines on iOS first. - JMac

2 Answers

5
votes

You almost certainly don't want to write assembly instructions to perform the stack manipulation. iOS is already on its third version of the ARM instruction set, having transitioned from ARMv6 through ARMv7 to ARMv7s. As of the iPhone 5, Apple has further added the artificial barrier that you may not submit an application with an ARMv6 fork that also supports the full iPhone 5 screen. I'm sure Apple's motivation is to ensure it can transition to processors without an ARMv6 compatibility mode at some point in the future but for us developers it obviously means not becoming too dependent on the specific instruction set.

That leaves threads. iOS has a full set of well-developed threading mechanisms and pthread is there to expose the relevant subset. Grand Central Dispatch tends to be the normal solution used now to ensure that different tasks can occur simultaneously so swallows most of the Internet documentation but the lower-level solutions remain.

Obvious trivial example, using an 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
votes

boost.coroutine (from Oliver Kowalke; reviewed from boost community last month) uses boost.context which supports ARMv6 (ARM Cortext Ax)