Copy on write in swift

Shreeya
2 min readMay 27, 2024

--

In the absence of mutation, values and references act exactly the same way.

Copy-on-write (CoW) is a memory management technique used in programming languages like Swift to optimize the performance of value types, such as arrays and dictionaries. When you create a copy of a value type, the actual copying of the data is deferred until one of the copies is modified. This can be more efficient than immediately duplicating the data.

In Swift, when you have a value type like an array, and you make a copy of it, both the original array and the copy initially point to the same memory location. When you modify one of the arrays, Swift checks if it’s the sole owner of the underlying memory. If it is, it can modify the data in place. However, if there are multiple owners (i.e., multiple references to the same array), Swift creates a new copy of the array’s data and then performs the modification. This ensures that the original array and any other copies remain unaffected by the change.

Now, the issue arises when multiple threads or concurrent tasks are involved. When one thread is reading an array while another thread is concurrently modifying it, the behavior depends on how the array is being modified and how Swift’s copy-on-write mechanism handles the situation.

Concurrent Write and Read

Here’s where things get tricky. In Swift, when you have a value type like an array (which is a struct), and you modify it, the copy-on-write mechanism kicks in. This means that if the array is being modified, and there are other references to it, a new copy of the array’s data is created to ensure that the modification doesn’t affect other references.

Here’s where the issue arises. While the modifying thread is creating a new copy of the array’s data, the reading thread might still be referencing the old data. If the modifying thread completes the write operation (thus deallocating the old storage), and if the reading thread attempts to access the array after this deallocation, it will end up trying to reference memory that has been deallocated, leading to a crash.

To put it simply, the crash occurs because the reading thread is trying to access memory that no longer exists. This is because the modifying thread has already created a new copy of the array’s data, leaving the old storage deallocated.

To avoid such crashes, it’s essential to ensure proper synchronization between threads when accessing shared mutable state like arrays. This can be achieved using synchronization mechanisms such as locks, queues, or Swift’s concurrency features to coordinate access and prevent race conditions.

Source:

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Shreeya
Shreeya

No responses yet

Write a response