Created
November 2, 2015 16:00
-
-
Save zwaldowski/fcc9ce35db4cfe2cfe0e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// 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