Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift array copy on write in a multithreaded environment

Tags:

ios

swift

Swift arrays are value types that copy on write. If a the original array is not mutated then the “copy” points to the same memory location.

Supposed we have a class referenced by multiple threads

class Foo {
    var numbers: [Int] = [1, 2, 3]
}
let foo = Foo()

If thread A “copies” numbers

var numbers = foo.numbers

and then later thread B replaces numbers with a different array instance

foo.numbers = [4, 5, 6]

will the original numbers array ([1, 2, 3]) be deallocated, resulting in incorrect checksum for freed object - object was probably modified after being freed when thread B attempts to access its elements?

like image 820
Steve Kuo Avatar asked Jul 08 '16 01:07

Steve Kuo


1 Answers

var numbers = foo.numbers will always contain [1, 2, 3] until you modify var numbers.

let foo = Foo()
// Thread A
var numbers = foo.numbers

// Thread b
foo.numbers = [4, 5, 6]

// Thread A again - 'var numbers' still has a "reference" to [1, 2, 3]
print(numbers) // "[1, 2, 3]"

I think you're misunderstanding how structs in swift act as value types. The original [1, 2, 3] array will not overwritten when you reassign foo.numbers.

Example

Say you have 10 threads all of which "copy" foo.numbers, at this point the array's memory is not copied.

var myTheadNumbers = foo.numbers

Lets say thread 1 modifies the array

myThreadNumbers.append(4)

[1, 2, 3] is copied to a new array which is then modified by appending 4.

Thread 1 now has it's own a single array of [1, 2, 3, 4] while threads 2-10 are still sharing the original [1, 2, 3]. That's what copy-on-write means for structs - you only take the performance hit for copying when you modify a struct and someone else has an old copy laying around.

Each one of those 10 threads acts like they have their own copy of [1, 2, 3] which is the meaning of value types.

like image 67
Kevin Avatar answered Sep 29 '22 02:09

Kevin