Always an Easier Way

Previously in Avoiding an Objective-C Pitfall #1 I discussed a more stable way of creating singletons in Objective-C.  As with all things in the world of Apple there’s always an easier way and that way comes to us via two very powerful yet unnoticed (in the Windows and Linux communities at least) APIs that Apple has contributed to the development community.  The first is a library that Apple developed to make multithreading safer and easier in a way that no other library ever has.  It’s called Grand Central Dispatch (a nod to New York City’s famous Grand Central Station) that reintroduces threads in terms of dispatch queues.  If you have never heard of it I highly recommend getting to know it.  Versions of it also exist for FreeBSD, Linux, and Windows.

The second is actually an extension to the C language that Apple submitted that is a default part of the clang/llvm C/C++/Objective-C compiler (the default compiler for Apple) called Blocks. If you’ve ever worked with closures in other languages such as Javascript then Blocks will instantly be familiar to you.  In fact, from here on out I will refer to these code sections as closures.  As with GCD, Blocks are supported on FreeBSD, Linux, and Windows.

So let’s get right into how all of this makes things easier in the realm of singletons. The first thing I recommend doing is creating a simple function to return a shared instance of a serial dispatch queue.  Yes, a singleton! 🧐

Screen Shot 2018-09-10 at 10.53.53 AM

Here we see things in action right off the bat. We use Grand Central Dispatch’s dispatch_once(…) function to create a single serial dispatch queue. Notice right away that there are no locks or @synchronized(){} blocks anywhere to be found.  That’s because the contract for the dispatch_once(…) function says that in the event of multiple threads calling it at once, only one thread will execute.  All other threads will be blocked until the currently executing thread completes.  And, in this case, the variable _serialQOnce acts as a predicate that will keep the closure from being executed more than once.  Initialized to zero, dispatch_once(…) will set that variable to a non-zero value upon completion. The body of the closure performs the actual creation of the singleton.

The reason we’re doing this first is because serial dispatch queues are extremely handy and this gives you a single, static queue that isn’t one of the system “global queues” that could become very busy.  The one produced by this function will be just for your application and your application only.

So let’s move on to using a serial dispatch queue to create an improved singleton factory for a class.  Serial dispatch queues have a unique property in that blocks placed on them are executed sequentially with respect to each other but asynchronously with respect to other queues (even other serial queues) and threads.  Boiled down this simply means that each item pulled off the queue (in FIFO order) is allowed to fully complete executing before the next item is pulled off the queue.  This is in contrast to a concurrent queue in which items are pulled off, started executing, and then the next item is pulled off and started executing without waiting for the previous item(s) to complete.

Think of it this way, suppose you have a corn maze that you let children run through.  Now imagine a line of children (your queue) waiting to enter the maze.  In a concurrent queue you would allow the children to enter the maze one at a time but you don’t wait for that child to finish the maze before you let the next child into the maze. Perhaps you separate them by only one second. The end result is that, depending on the child’s abilities, such as how fast they can run, the first child into the maze may not be the first one out of the maze.  In fact the first child in might even be the very last one out!

In a sequential queue however, you still have your corn maze and your line of children (your queue) but this time as you let a child in you wait for them to complete the maze before you let the next child in.  This has the effect of guaranteeing that the first child in is the first child out and, by extension, the last child in is the last child out.  But it also has the effect that each child is alone in the maze and able to complete it entirely at their own pace – they’re not going to get run over by another child.  This is the effect that we are going to take advantage of.

So let’s look at the code…

Screen Shot 2018-09-10 at 11.36.36 AM

It looks almost the same except that the body of code that use to be inside a @synchronized(){} block is now inside a closure that is executed on a serial dispatch queue.  The dispatch_sync(…) function (the “sync” has nothing to do with the fact that we’re using a serial queue) will wait until the closure provided has completed executing before it returns. This guarantees that the _instance variable will be populated when the function completes. The “__block” storage modifier on the _instance variable simply allows it to be modified from inside the closure.  Also any concurrent calls to this method are guaranteed to happen sequentially so that two instances of the same class are not created at the same time.

So why is this better? Well, that depends on your point of view I suppose.  But for me it eliminates the @synchronized(){} construct that is known to have a rather high time cost.  Also I feel it looks, overall, a little more elegant.

Avoiding an Objective-C Pitfall #1

Below is a very commonly used design pattern in Objective-C.

CommonDesignPattern

It’s the typical Objective-C “Singleton Pattern” because it does just that.  Returns a singleton of the class it belongs to.  If we take a look at an example that uses it we can see it in action.

Screen Shot 2017-05-16 at 1.07.57 PM

The “@synchronized(self)” statement ensures that only one thread at a time enters that inner block and keeps more than one copy of the class from being created.  Without it two or more threads might just happen to get past the “if(_inst == nil)” statement before one of the threads manages to complete the assignment to the static local variable “_inst”.

If you run this program you get the output you’d expect:

Screen Shot 2017-05-16 at 1.22.27 PM

The class “Test1” created exactly ONE instance of itself, stored it in the static local variable “_inst” and then returned it.  If the program had called the class method a second time it would have gotten the exact same instance that was created in the first call like so:

Screen Shot 2017-05-16 at 1.28.55 PMScreen Shot 2017-05-16 at 1.29.08 PM

All well and good!  Now, let’s add a little wrinkle to the situation by creating a subclass of “Test1”:

Screen Shot 2017-05-16 at 1.08.34 PM

In this example, “Test2” inherits directly from “Test1”.  It’s very simple and doesn’t even override any methods.  We’ve also set the second instance object in the main function, “o2”, to get the result of calling [Test2 instance] instead of [Test1 instance].  But since we didn’t override anything it’s still really calling the same method found in “Test1”.  Now, let’s run it and see what output we get.

Screen Shot 2017-05-16 at 1.41.44 PM

Now, for some of you, this is not what you were expecting to see.  You were probably expecting to see “Returned Class 2 = Test2“.  However the more I thought about it this was exactly what I was expecting to see.  The reason for this is simple.  Static local variables are scoped to the method in which they are created.  Since this was a class method (belongs to the class definition rather than instances of the class) it belongs to the class in which the method was defined.  Bottom line this would have been EXACTLY as if I had coded it as follows:

Screen Shot 2017-05-16 at 3.19.15 PM

Notice that the static local variable is now your everyday, garden variety global variable.  The only difference now is that from a scope perspective it can be “seen” from the entire program instead of just inside the [Test1 instance] method.

Coincidentally, if you reverse the two calls to the “instance” method you’ll get instances of “Test2” instead of “Test1”.

Screen Shot 2017-05-16 at 3.45.09 PMScreen Shot 2017-05-16 at 3.45.22 PM

Why didn’t an instance of “Test1” get created?  Because we called [Test2 instance] instead of [Test1 instance].  But why since we didn’t override that method in “Test2?”  For a better explanation of meta-classes in Objective-C I refer you to this excellent blog post: What is a meta-class in Objective-C?

But there’s also another more problematic issue with this test case.  That “@synchronized(self)” statement?  It’s rendered completely useless in our example if [Test1 instance] is called from one thread and [Test2 instance] is called at the same time from another thread.  The reason is evident in the second line of the output.  Even though the method belongs to the class definition for “Test1” we’re calling it from the scope of the subclass definition “Test2”.  (Again, read the blog post at the link given above.) So if there are two threads and one thread calls [Test1 instance] and the other thread calls [Test2 instance] that synchronization lock will be locking on two entirely different objects because the “self” properties in both calls will be pointing to two different objects.  Bottom line:  you could end up with an instance of the wrong class than what you were expecting.

Below is one solution albeit not the optimal one.  We simply override the class method in “Test2.”

Screen Shot 2017-05-16 at 1.59.34 PMScreen Shot 2017-05-16 at 2.09.22 PM

Why isn’t this the optimal solution?  Because you have blatant code duplication.  Not just within the program as a whole but even worse, given that we’re talking about Object Oriented Programming, within the a subclass!

No, a better solution is needed.  And one that I’ve come up with in my own code is only slightly more complicated but, I think, solves the problem very nicely without adding much memory or CPU time overhead.  Let’s look at the newly refactored “instance” method.

Screen Shot 2017-05-16 at 4.16.12 PM

We will now store the singleton instances in a dictionary using the class name as the key. This ensures that if we call this method using [Test2 instance] we get an actual instance of “Test2” and if we call it using [Test1 instance] we get an actual instance of “Test1”.  Moreover we still only create just one instance of any given class.

Finally we change the object being synchronized on to simply the static base class, [Test1 class], rather than allowing it to be based on the “self” property.

So, after a quick change to the “main” function to test the results.

Screen Shot 2017-05-16 at 4.24.04 PMScreen Shot 2017-05-16 at 4.24.30 PM

And you can now see that the results are more inline with what you would expect without having to duplicate code in the subclasses.