Apr 30 2008

Coroutines in Objective-C

I’ve started using NSOperation in a few places in Cloudy, which means I’m backsliding into using threads and locking and so forth. It definitely makes writing network code easier than Cocoa’s asynchronous API, but I really don’t want to get into a morass of threads.

What I’d really like to use are Actors. In a nutshell, an Actor is an object that has its own [cooperative] thread and message queue. Actors interact by message-passing instead of shared state. The idea is to eliminate the need for standard synchronization primitives like semaphors and locks, and get rid of the race conditions and deadlocks that plague multi-threaded programs.

The page I linked to above is from Revactor, a new Actor implementation for Ruby 1.9; Actors are also built into languages like Erlang and Io.

The only hard part about implementing Actors in Obj-C appears to be the underlying dependency on coroutines. Steve Dekorte [author of Io] has a C coroutine implementation ; when I discovered that last year, I then found an Objective-C wrapper for it, but that relies on a HigherOrderMessaging library which is incompatible with OS X 10.5 and hasn’t yet been updated.

So I’ve gone DIY.

I started with Steve Dekorte’s coroutine library, but unfortunately it doesn’t build on 10.5 … and when I got it to build, I then ran into a bug in the system header … and by the time I’d worked around that, I knew the code well enough that I pretty much rewrote it. Doing this made it much shorter and clearer, since Steve’s code is cross-platform and supports three different implementations, while all I care about is OS X 10.5. I got it down to 150 lines of C.

Then I wrote a pretty simple Objective-C wrapper around it, under 200 lines. (Here’s the header.)

Come ‘n’ get it…

The work in progress is in my Mercurial repository if you want to check it out. It’s grandly titled “Actors”, but all that’s in it so far is the coroutine implementation.

Needless to say, this is currently for amusement purposes only; do not use it in real code. In particular, I strongly suspect that there are going to be problems getting Objective-C exceptions and autorelease pools to work correctly in coroutines. I’ll try to explore that next.


7 Responses to “Coroutines in Objective-C”

  • paracelsvs (LJ) Says:

    Well, I made this earlier:

    http://www.cocoadev.com/index.pl?CSCoroutine

    It has no external dependencies, is very short and simple, and uses proxy objects to make invocations as simple and straightforward as possible. It is thread safe and allows having coroutines jump between threads. Using it together with exceptions is possible but requires care.

    See http://www.cocoadev.com/index.pl?CSCoroutineTest for examples of how it works.

  • Jens Ayton Says:

    “Actors interact by message-passing instead of shared state.”

    I love the way people keep reinventing OO. :-) (I like the idea of actors, mind, but they’re basically OO as described by Alan Kay with the implied assumption of synchronous operation removed.)

  • chanson (LJ) Says:

    The wonderful thing about NSOperation is that, so long as you stay away from shared state, you don’t have to manage threads yourself.

    Furthermore, there’s no reason that actors have to correspond to cooperative threads. There’s nothing inherently superior in cooperative threading - if you can use preemptive OS-supplied threading, especially via indirect mechanisms like NSOperation, you can take better advantage of multiple CPUs than if you try to multiplex everything.

    The real problem in dealing with threaded code is manipulation of shared state, and that’s going to be a problem regardless of whether your threads are preemptive or cooperative. The only way to truly solve it is to avoid shared state as much as possible, and be as rigorous as possible in what you can’t avoid. Going cooperative-everything just sweeps the problem under the rug; you still have to get all your “yield” calls right, for one thing.

  • Steven Harms Says:

    A cloudy-related post sans Cloudy himself. For shame!

  • Jens Alfke Says:

    Steven — You mean “herself” =)

  • Jens Alfke Says:

    Jens — Actually, the Actor model dates back to 1973, so it’s unfair to say it’s “reinventing OO”. If anything, it’s probably closer to the original simulation-based roots of Simula than Alan Kay’s work on Smalltalk-72.

    And asynchronous message delivery is a huge change. I’ve been trying to follow the theoretical underpinnings, and they’re very weird, being directly based on Special Relativity’s notions of limited causality. (And in fact this is all like the way peers communicate on a network, so it’s going to be useful for me whether or not I implement Actors at the micro-level inside Cloudy itself.)

  • Steven Harms Says:

    Jens,

    I should be rather embarrassed by this error considering that I see the undersides of clouds all day long.

    Apologies to Ms. Cloudy,

    Steven

Leave a Reply