Apple's Grand Central Dispatch (GCD) is great, but only works on iOS 4.0 or greater. Apple's documentation says, "[A] serialized operation queue does not offer quite the same behavior as a serial dispatch queue in Grand Central Dispatch does" (because the queue is not FIFO, but order is determined by dependencies and priorities).
What is the right way to achieve the same effect as GCD's serial dispatch queues while supporting OS versions before GCD was released? Or put another way, what is the recommended way to handle simple background processing (doing web service requests, etc.) in iOS apps that want to support versions less than 4.0?
Seems like people are going to a lot of effort to rewrite NSRunloop. Per the NSRunloop documentation:
So surely the trivial answer would be, to create a usable queue:
To add a task to the queue:
Per the Threading Programming Guide section on Run Loops:
So you've got an explicitly serial queue. Of course, mine isn't fantastically written because I've told the run loop to run forever, and you may prefer one you can terminate later, but those are easy modifications to make.
There are things NSOperationQueue documentation writer forgot to mention, making such implementation seem trivial when in fact it's not.
Setting the maximum concurrent operation count to 1 is guaranteed to be serial only if NSOperations are added to the queue from same thread.
I'm using another option because it just works.
Add NSOperations from different threads but use NSCondition to manage queuing. startOperations can (and should, you don't want to block main thread with locks) be called with performSelectorOnBackgroundThread...
startOperations method represents single job that consists of one or more NSOperations.
That's it!
How about this PseudoSerialQueue? It is a minimal implementation like the Dispatch Serial Queue.
How to use:
If the processing is in the background anyway, do you really need it to be strictly in-order? If you do, you can achieve the same effect simply by setting up your dependencies so 1 depends on 0, 2 on 1, 3 on 2, etc. The operation queue is then forced to handle them in order. Set the maximum concurrent operation count to 1, and the queue is also guaranteed to be serial.
you can simulate it using
NSOperationQueue
, then just set the task count to one.EDIT
-- oops, should have read more carefully. the fifo solution follows:
i can't think of a way that the majority of ios devs would use in your situation.
i'm not afraid of writing threaded programs, so here is one solution:
main
. only one may exist at a time.the NSOperation subclass pulls the workers from the fifo worker queue until the fifo worker queue is exhausted.
when the fifo work queue has workers and no active child operation, it creates a child operation, adds it to its operation queue.
there are a few pitfalls if you aren't comfortable writing threaded programs -- for this reason, this solution is not ideal for everybody, but this solution would not take very long to write if you are already comfortable using all the technologies required.
good luck