I have already asked this question in the official Apple developer forums, but unfortunately did not get an answer. I am currently trying to build some simple concurrent data structures in Swift and couldn't find a way to call OSAtomicCompareAndSwapPtrBarrier
from Swift code. The signature is
OSAtomicCompareAndSwapPtrBarrier(
__oldValue: UnsafePointer<()>,
__newValue: UnsafePointer<()>,
__theValue: UnsafePointer<UnsafePointer<()>>)
which in C would be
OSAtomicCompareAndSwapPtrBarrier(
void *__oldValue,
void *__newValue,
void * volatile *__theValue)
I couldn't find a way to create an UnsafePointer<UnsafePointer<()>>
. Just a short code example:
class Stack<A> {
var __head: Node<A>
init() {
__head = Node()
}
func push(elem: A) {
var newNode = Node<A>()
newNode.elem = elem
var currentHead: Node<A>
do {
currentHead = __head
newNode.next = currentHead
} while(!OSAtomicCompareAndSwapPtrBarrier(¤tHead, &newNode, &__head))
}
}
class Node<A> {
var elem: A?
var next: Node<A>?
}
Using &__head
obviously does not work, as it only creates an UnsafePointer<()>
. So how can I create the UnsafePointer<UnsafePointer<()>>
here?
edit:
In C I can use it as follows (I don't normally use C, so this code may be terribly wrong):
#include <stdio.h>
#include <stdlib.h>
#include <libkern/OSAtomic.h>
typedef struct {
int bar;
} foo;
int main(int argc, const char * argv[]) {
// insert code here...
foo * volatile f = malloc(sizeof(foo));
foo *n = malloc(sizeof(foo));
f->bar = 1;
foo *old = f;
n->bar = 3;
OSAtomicCompareAndSwapPtrBarrier(old, n, &f);
free(old);
printf("%d\n", f->bar);
free(f);
return 0;
}
This is an example how to use OSAtomicCompareAndSwapPtrBarrier or OSAtomicCompareAndSwapPtr in Swift:
public final class AtomicReference<T : AnyObject> {
private var _value : T
public var value : T {
get {
OSMemoryBarrier()
return _value
}
set {
OSMemoryBarrier()
_value = newValue
}
}
private let pointer : UnsafeMutablePointer<UnsafeMutablePointer<Void>> = UnsafeMutablePointer.alloc(1)
public init(_ value : T) {
self._value = value
pointer.memory = UnsafeMutablePointer<Void>(Unmanaged.passUnretained(value).toOpaque())
}
deinit {
pointer.destroy()
}
public func compareAndSwap(#oldValue : T, newValue: T) -> Bool {
let ov = Unmanaged.passUnretained(oldValue)
let nv = Unmanaged.passUnretained(newValue)
if OSAtomicCompareAndSwapPtrBarrier(UnsafeMutablePointer<Void>(ov.toOpaque()), UnsafeMutablePointer<Void>(nv.toOpaque()), pointer) {
_value = newValue
return true
} else {
return false
}
}
}
This code is a class which works like AtomicReference in Java. It enables you to avoid thread locks in some cases using atomic operations instead. Atomic operations usually provide higher performance in case of high concurrency.
The compareAndSwap function will change the value only if the previous value is the same as oldValue. For instance:
class LockArray {
var value = NSArray()
let lock = NSLock()
func addItem(item : Int) {
lock.lock()
value = value.arrayByAddingObject(item)
lock.unlock()
}
}
class AtomicArray {
let reference = AtomicRefence<NSArray>([])
func addItem(item : Int) {
while true {
let oldValue = reference.value
let newValue = oldValue.arrayByAddingObject(item)
if reference.compareAndSwap(oldValue: oldValue, newValue: newValue) {
break
}
}
}
}
Both of these classes are thread-safe and do the same thing. However, the second one will work better with high concurrency.