jack sexton
jack sexton

Reputation: 1287

How to create UnsafeMutablePointer<UnsafeMutablePointer> in swift

The function:

public func OSAtomicCompareAndSwapPtr(_ __oldValue: UnsafeMutableRawPointer!, _ __newValue: UnsafeMutableRawPointer!, ___theValue: UnsafeMutablePointer<UnsafeMutableRawPointer?>!) -> Bool

requires a type of UnsafeMutablePointer<UnsafeMutableRawPointer?> for the a parameter theValue but I'm having trouble figuring out how to make one from a type UnsafeMutablePointer<T?>

Any thoughts on how I could do this?

EDIT:

for the curious about why I am trying to do this, I am trying to create a generic wrapper around this to create a bounded MPMC queue in swift as outlined in this blog post. Here is my wrapper so far

func compareAndSwap<T: AnyObject>(current: T?, future: T?, toPtr: UnsafeMutablePointer<T?>) -> Bool {
    let currentPtr = current.map(Unmanaged.passUnretained)?.toOpaque()
    let futurePtr = future.map(Unmanaged.passRetained)?.toOpaque()

    if OSAtomicCompareAndSwapPtr(currentPtr, futurePtr, ????) {
        return true
    }
    return false

Upvotes: 0

Views: 609

Answers (1)

kennytm
kennytm

Reputation: 523734

In Swift 3, use .withMemoryRebound to reinterpret-cast that "T**" pointer to a "void**" pointer:

return toPtr.withMemoryRebound(to: (UnsafeMutableRawPointer?).self, capacity: 1) {
    OSAtomicCompareAndSwapPtr(currentPtr, futurePtr, $0)
}

Note that

  • OSAtomicCompareAndSwapPtr has been deprecated in favor of the C11 functions like atomic_compare_and_exchange_strong, which unfortunately you cannot use in Swift. This is a known issue.
  • The blog post's atomic operations uses "acquire", "release" and also "relaxed" memory order. The OSAtomic libraries provides only the "seq_cst" and "relaxed" order (the Barrier vs non-Barrier variant of each function). So your Swift translation cannot be a 1:1 functional copy of the C++ code.

There is also a thin wrapper library timehop/Atomics which hides all the dangerous casts for you (it is not generic, however).

var toPtr = HOPAtomicReference(object: ...)
...
return toPtr.compareTo(current, andSetObject: future)

Upvotes: 1

Related Questions