Read more of this story at Slashdot.
I try to avoid the following pattern, but it’s the best call from time to time.
Foo does some startup in a background serial queue. Parts of Foo’s public API don’t work until that startup has completed, so I want those methods to block callers until startup has completed.
I have not found a great way of dealing with this.
I do something like this:
- init
create_lock()
lock()
startupOnSerialQueue()
completion: unlock()
- someMethod
lock()
do_the_thing()
unlock()
Ugh.
With this method, someMethod is blocked while startupOnSerialQueue() is happening.
And someMethod also gets a lock all the rest of the time. That’s not a big deal, because, in practice, someMethod is super-fast. But it wouldn’t actually have to have that lock except right at startup.
This feels inelegant to me. It’s simple enough, and it works, but I don’t like it.
Do you know of a better solution?
My first thought is that dispatch_once would help — but it wouldn’t. (Not that I can see.) It would make sure startupOnSerialQueue is called once, but doesn’t solve the problem of blocking use of someMethod until startupOnSerialQueue has completed.
Another possibility: someMethod could put do_the_thing() inside a dispatch_sync block that runs on the background serial queue. But that also seems inelegant. Needlessly complicated.
This reminds me of the old joke. Man: “Doc, it hurts when I go like this!” Doctor: “Well don’t go like that!”
Except that I will go like that when everything else about the design is perfect. Since I can keep the async startup internal to Foo, it’s able to implement its public API without infecting anything else.
So my only question is if there’s a better pattern for handling this.
Read more of this story at Slashdot.
Read more of this story at Slashdot.