如何使用Swift的OSAtomicCompareAndSwapPtrBarrier?

时间:2014-07-15 12:28:04

标签: concurrency swift atomic

我已经在官方Apple developer forums中提出了这个问题,但遗憾的是没有得到答案。我目前正在尝试在Swift中构建一些简单的并发数据结构,但是找不到从Swift代码调用OSAtomicCompareAndSwapPtrBarrier的方法。签名是

OSAtomicCompareAndSwapPtrBarrier(
  __oldValue: UnsafePointer<()>,
  __newValue: UnsafePointer<()>,
  __theValue: UnsafePointer<UnsafePointer<()>>)

在C中将是

OSAtomicCompareAndSwapPtrBarrier(
  void *__oldValue,
  void *__newValue,
  void * volatile *__theValue)

我找不到创建UnsafePointer<UnsafePointer<()>>的方法。只是一个简短的代码示例:

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(&currentHead, &newNode, &__head))
  }
}

class Node<A> {
  var elem: A?
  var next: Node<A>?
}

使用&__head显然不起作用,因为它只会创建UnsafePointer<()>。那么如何在这里创建UnsafePointer<UnsafePointer<()>>

修改

在C中我可以按如下方式使用它(我通常不使用C,所以这段代码可能非常错误):

#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;
}

2 个答案:

答案 0 :(得分:1)

这是一个如何在Swift中使用OSAtomicCompareAndSwapPtrBarrier或OSAtomicCompareAndSwapPtr的示例:

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
        }
    }
}

此代码是一个类似于Java中的AtomicReference的类。它使您可以在某些情况下使用原子操作来避免线程锁定。在高并发性的情况下,原子操作通常可以提供更高的性能。

仅当前一个值与oldValue相同时,compareAndSwap函数才会更改该值。例如:

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
            }
        }
    }
}

这两个类都是线程安全的,并且做同样的事情。但是,第二个将更好地与高并发性。

答案 1 :(得分:0)

尝试

var pointer = UnsafePointer< UnsafePointer< Node<A> > >.alloc(1)
pointer.initialize(&__head)

这显式分配指针并填充它。

PS:完成后忘了打电话给pointer.dealloc(1) ......

编辑:您可能必须明确创建与上述内容类似的UnsafePointer< Node<A> >,而不是使用&__head并将其传递给initialize而不是......