Swift: Pointers everywhere
Unsafety? More like FUnsafety
Edit: Updated with new information to clarify that UnsafePointer<T>
expects the number of instances of T
, not the size in bytes.
Today let's discuss UnsafePointer<T>
. Perhaps you want to use a fancy function like OSAtomicIncrement32
to keep a running counter across threads and GCD queues, without any locking, blocking, or race conditions. How can we accomplish that in Swift?
var count = UnsafePointer<Int32>.alloc(1)
count.initialize(0)
//do this wherever needed
OSAtomicIncrement32(count)
//read the result
println("\(count.memory)")
//don't forget to free
count.dealloc(1)
First, we declare an unsafe pointer to an Int32
and tell Swift how many of that type we want to allocate. Edit: I previously thought the param was the byte size, but John McCall clued me in that Swift is smart enough to know the size of T
, and just wants to know how many of those you'd like.
Next we can't forget to initialize the value to zero, otherwise our count may start with some garbage value (or it may not!), leading to unpredictable behavior.
The memory
property is how we access the underlying type, assuming Swift understands that type. In the case of Int32
, it does so we're good to go. The type of memory
is determined by the generic type parameter we specified on the previous line.
Now we've got a fancy UnsafePointer<Int32>
and can call the OSAtomicIncrement32
function. Again, we can access the current value from the memory
property.
Last but not least, we must dealloc
the memory. Edit: Pass the number of items that were originally allocated. This is an optimization, rather than having to lookup the size from the allocator on every dealloc. Passing a different number from what you passed in alloc
is undefined behavior.
Now go forth and point with ease!
Part 1 Swift: Manual retain/release
Part 2 Swift: withUnsafePointerToElements
This blog represents my own personal opinion and is not endorsed by my employer.