Skip to content

Instantly share code, notes, and snippets.

@zwaldowski
Created November 2, 2015 16:00
Show Gist options
  • Save zwaldowski/fcc9ce35db4cfe2cfe0e to your computer and use it in GitHub Desktop.
Save zwaldowski/fcc9ce35db4cfe2cfe0e to your computer and use it in GitHub Desktop.
/// Compare and swap references.
///
/// This function compares the reference `old` to the reference in the
/// location referenced by `to`. If the references match, this method
/// stores the reference `new` to that location atomically.
///
/// Similar to a pointer compare-and-swap, but safe for owned (retaining) pointers:
/// - ObjC: `MyObject *__strong *`
/// - Swift: `UnsafeMutablePointer<MyObject>`
/// If the swap is made, the new value is retained by its owning pointer.
/// If the swap is not made, the new value is not retained.
///
/// - warning: This function is not generally safe; the `to` reference
/// *must* be a stable pointer in order to actually be atomic. This
/// means it must be a stored property of a class or a constant buffer
/// pointer. This can include storage backed by `ManagedBuffer`
/// if the size of the buffer is constant, though (perhaps ironically)
/// it's safest to use the unsafe pointer types.
/// - returns: `true` if swapped, `false` otherwise.
private func compareAndSwap<T: AnyObject>(old old: T?, new: T?, to toPtr: UnsafeMutablePointer<T?>) -> Bool {
let oldRef = old.map(Unmanaged.passUnretained)
let newRef = new.map(Unmanaged.passRetained)
let oldPtr = oldRef?.toOpaque() ?? nil
let newPtr = newRef?.toOpaque() ?? nil
if OSAtomicCompareAndSwapPtr(UnsafeMutablePointer(oldPtr), UnsafeMutablePointer(newPtr), UnsafeMutablePointer(toPtr)) {
oldRef?.release()
return true
} else {
newRef?.release()
return false
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment