Concurrency's Present: Queues and Combine

Episode #191 • May 30, 2022 • Subscriber-Only

Before developing Swift’s modern concurrency tools, Apple improved upon threads with several other abstractions, including operation queues, Grand Central Dispatch, and Combine. Let’s see what these newer tools brought to the table.

Queues and Combine
Introduction
00:05
Operation queues
01:59
Operation queue problems
14:34
GCD
19:43
GCD problems
41:28
Combine
47:13
Next time: Tasks
61:18

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

Introduction

So even using _read and _modify cannot fix this synchronization problem. It simply is not possible to lock property mutations in this style, and is why we need to either create one-off methods for mutating state or leverage the modify method.

This goes to show just how tricky multithreading and data races can be. What seems to be reasonable can often be incorrect and lead to incorrect results. The main problem with locks is they are fully decoupled from the concurrency tool we are using, which in this case is threads. Ideally the locking mechanism has intimate knowledge of how we are running multiple units of work at once in order to guarantee synchronization. This is what Swift’s new concurrency tools provide for us, but before we can discuss that there are a few more things to discuss.

So, Apple’s Thread class was the primary abstraction people would use on Apple’s platforms in order to unlock asynchrony and concurrency back in the day. It comes with some interesting features, such as priority, cancellation, thread dictionaries and more, but they also lack in many ways:

  • Threads don’t support the notion of child threads so that things like priority, cancellation and thread dictionaries don’t trickle down to threads created from other threads.
  • It’s easy to accidentally explode the number of threads being used.
  • It’s hard to coordinate between threads.
  • Threaded code looks very different from unthreaded code.
  • And the tools for synchronizing between threads are crude.

Now there’s a good chance that most of our viewers have never used threads directly in their codebase because ever since macOS Leopard, released 15 years ago, Apple has built abstractions on top of threads to help fix a lot of the problems we just uncovered. This includes operation queues, Grand Central Dispatch and even Combine. Let’s take a look at how those technologies improved upon threads, and see where they fall short.

This episode is for subscribers only.

Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

See plans and pricing

Already a subscriber? Log in

References

NSOperation

Mattt • Monday Jul 14, 2014

In life, there’s always work to be done. Every day brings with it a steady stream of tasks and chores to fill the working hours of our existence. Productivity is, as in life as it is in programming, a matter of scheduling and prioritizing and multi-tasking work in order to keep up appearances.

libdispatch efficiency tips

Thomas Clement • Thursday Apr 26, 2018

The libdispatch is one of the most misused API due to the way it was presented to us when it was introduced and for many years after that, and due to the confusing documentation and API. This page is a compilation of important things to know if you’re going to use this library. Many references are available at the end of this document pointing to comments from Apple’s very own libdispatch maintainer (Pierre Habouzit).

Modernizing Grand Central Dispatch Usage

Apple • Monday Jun 5, 2017

macOS 10.13 and iOS 11 have reinvented how Grand Central Dispatch and the Darwin kernel collaborate, enabling your applications to run concurrent workloads more efficiently. Learn how to modernize your code to take advantage of these improvements and make optimal use of hardware resources.

Introducing Swift Atomics

Karoy Lorentey • Thursday Oct 1, 2020

I’m delighted to announce Swift Atomics, a new open source package that enables direct use of low-level atomic operations in Swift code. The goal of this library is to enable intrepid systems programmers to start building synchronization constructs (such as concurrent data structures) directly in Swift.

Downloads