Concurrent Computing and Programming with Grand Central Dispatch
We are going to study concurent programming with Swift on iOS using the native Grand Central Dispatch ( GCD
) framework. If you are not familiar with concurrent programming I suggest you start by taking a look at wikipedia . Let’s get started by studying the philosophy and good practises behind this API.
Grand Central Dispatch
GCD
(Grand Central Dispatch) is a framework that provides low-level APIs to handle concurrent programming on iOS, macOS, tvOS and watchOS platforms. All of the higher-level frameworks that offer competitive management at Apple, such as NSOperation
, are based on GCD
. These APIs allow you to divide the work of a process into individual tasks, and then help orchestrate the execution of these tasks in parallel or sequentially using a queue. It allows us to abstract from the notion of thread, processor or heart, and optimizes resource management at the same time with its own thread-pool.
The Queues
A fundamental notion on which GCD
is based is FIFO (First In, First Out). The tasks that we want to execute will first be inserted into these queues, then GCD will come to retrieve them individually to dispatch them to the right threads / processors / hearts. We can distinguish 2 kinds of file:
- Concurrent file: Performs multiple tasks in parallel
- Sequential or Serial file: performs one-to-one tasks in series
Here are the 3 categories of existing files:
Main queue
: equivalent to the main thread that primarily handles the application's UI. All of the UI calls must be done on this queue.Global queue
: the system provides us with 3 global tails with different priorities (HIGH, DEFAULT and LOW). These 3 files are of the Concurrent type.Custom queue
: queues that can be created manually and of the desired type (Serial or concurrent).
GCD in Practice
Let’s start by creating one of the 3 categories of queues:
For the creation of a custom queue , we first define an identifier (it is recommended to use the reverse-DNS format).
Now that we know how to create files, how do we use them? It’s very simple, thanks to the “dispatcher”! Here is a small example:
Let’s break down all that. We get to start a low priority queue. Then we “dispatch” a block of code asynchronously on the low priority queue previously recovered. This code block asynchronously fetch data to store it in the data
variable. Finally we update our view
in the main thread with the data recovered. It is important to perform the last step in the main thread because UIKit
is not threadsafe and if you update your components in another thread your application may crash or have undefined behavior.
Here the console will show:
before
after
inside async block
inside main Queue block
finished!
Going Deeper
With GCD
you can manage all that concerns the concurrent programming. We will see in this section different cases of use a little further.
Let’s discuss a use case where you have several tasks to perform and you want to wait until all these tasks are done before doing anything else. For this it is necessary to use the DispatchGroup
:
In order to wait for all the tasks to be done we create a group
and in our loop we define when a task starts in the group and especially define when the task is finished. We must imagine this as a counter, each enter
this counter is incremented by 1, and each leave
it is decremented by 1. At the end we define a notif
bloc which listens to the counter of the group
and which executes the block in the given queue
when he gets to 0. The console output here would be: (Finished job order may differ)
Starting job 0
Starting job 1
Starting job 2
Starting job 3
Starting job 4
Starting job 5
Starting job 6
Starting job 7
Starting job 8
Starting job 9Finished job 3
Finished job 2
Finished job 1
Finished job 4
Finished job 0
Finished job 9
Finished job 5
Finished job 6
Finished job 8
Finished job 7All jobs done!
A second very useful case may be wanting to execute code after a certain time. If you have this kind of case immediately think about GCD
and its asyncAfter
method:
Conclusion
GCD
is a very powerful framework that allows you to really get away from the low-level constraints inherent in concurrent programming. However to fully use it to this potential, you need to be careful with shared memory problems and syncronization. Take a deeper look here.