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.

Thoughts on GNUstep

For those that don’t know GNUstep is a project that started many years ago to help bring Objective-C to the masses using operating systems other than Mac OS X macOS.  Actually, Objective-C already existed on any platform that had access to the GCC compiler suite but what GNUstep sought to do was bring the primary frameworks (libraries) that were being used on macOS to make porting Mac applications to other platforms a lot easier.  In particular we’re talking about the Foundation and AppKit libraries.

For the most part they’ve nailed it on the head for simple applications and the Foundation library seems rock solid and fairly up-to-date with the Apple versions.  In fact the Foundation library seems to be up-to-date with at least macOS 10.9 and some of 10.10.

That said, there are a couple of places where people, including me, are having serious problems with GNUstep.  I have to add at this point that these are constructive criticisms!  The GNUstep folks had a definite goal in mind when they started and I have to say that they hit the nail on the head with this.  Also, like many open source projects, it’s an all volunteer army where people have day jobs and others simply lose interest for other projects.  In fact, the introduction of Swift has definitely contributed to that last point – many people have given up on Objective-C and jumped on the Swift bandwagon.

1. They Keep Breaking It

This mainly applies to the AppKit libraries when trying to use Objective-C 2.0 features such as the non-fragile ABI and ARC.  If you want to build your Objective-C 2.0 projects with the non-fragile ABI then you’re not going to be able to use the AppKit libraries.  Otherwise you’re applications will crash with a notice about mismatched ABIs.  The solution is to build without non-fragile ABI support.  This is not always desirable.

2. Strict Adherence to macOS Paradigms

Apple’s operating systems (macOS, iOS, watchOS, tvOS, etc.) all have this paradigm where basically everything is a directory.  Especially Frameworks and GUI Applications.  GNUstep tries its best to replicate this paradigm on other platforms but the truth is that it just isn’t necessary and adds a huge amount of complexity to the build process and the resulting product. The paradigm works very well indeed on Apple’s operating systems because there is support for the paradigm built right into the operating systems.  But on other operating systems such as Windows and Linux this paradigm doesn’t work so good.  In my opinion, and I’m not alone, it would be best to simply follow the best practices of those other platforms rather than trying to hammer a square peg into a round hole.  This applies to packaging too.  The default package manager for each platform should be used.  It’s less confusing for users of those platforms.

2.1. This Applies to GUI Applications Too

The GNUstep GUI applications ALL look like they were all written about 30 years ago.  They use concepts and HID guidelines that harken back to the NeXT operating system from whence everything is modeled from.  Even Apple has dropped most if not all of these old HID paradigms in favor of ones that are more modern and practical.  I mean, honestly, who has main menus that just hover somewhere detached from the main window of the application.  Really?

Yeah, okay, I know – GNUstep has this neat pluggable theme system and can be customized but 1) this is highly problematic (see point #1 above) and 2) it is not well documented – if at all.  And if it is documented you can’t find it unless you spend years scouring the web and happen to stumble across it like I did when I found this some FOUR years after it was first posted(scroll all the way to the end of the post to “Step 15: Making it Look like a Linux Application“)

3. Makefiles

Everything should be moved to CMake.  ’nuff said.

4. Distribution

There is no support in GNUstep for packaging your applications for distribution to system that don’t already have the GNUstep libraries on them.  I’ve seen ONE very outdated partial document describing one way to do it but that’s it.

How to Fix This

In an upcoming post that I’ll be sure to link to this one I’ll outline some steps for addressing these issues.  At least a couple of them I have already started work on: https://github.com/GalenRhodes/Rubicon