> On Apr 25, 2017, at 1:08 PM, Shawn Erickson <shaw...@gmail.com> wrote:
> 
> 
> On Mon, Dec 5, 2016 at 9:28 AM Joe Groff via swift-users 
> <swift-users@swift.org> wrote:
> 
>> On Dec 4, 2016, at 4:53 PM, Andrew Trick via swift-users 
>> <swift-users@swift.org> wrote:
>> 
>> 
>>> On Nov 30, 2016, at 5:40 AM, Anders Ha via swift-users 
>>> <swift-users@swift.org> wrote:
>>> 
>>> Hi guys
>>> 
>>> I have recently started adopting lock-free atomics with memory fences, but 
>>> it seems Swift at this moment does not have any native instruments.
>>> 
>>> Then I read a thread in the Apple Developer Forum 
>>> (https://forums.developer.apple.com/thread/49334), which an Apple staff 
>>> claimed that all imported atomic operations are "not guaranteed to be 
>>> atomic". But for my tests with all optimizations enabled (-Owholemodule and 
>>> -O), the OSAtomic primitives and stdatomic fences do not seem going wild.
>>> 
>>> Is these `atomic_*` and `OSAtomic*` primitives really unsafe in Swift as 
>>> claimed? It doesn't seem like the Swift compiler would reorder memory 
>>> accesses around a C function call that it wouldn't be able to see through.
>> 
>> Did you get an answer to this? I’m not sure what led you to believe the 
>> primitives are unsafe in Swift. Importing them doesn’t change their 
>> semantics.
> 
> If you apply them to memory you allocated manually with malloc/free on 
> UnsafeMutablePointer's allocation methods, then yeah, they should work as 
> they do in C. That's the safest way to use these functions today. Passing a 
> Swift `var` inout to one of these functions does not guarantee that accesses 
> to that var will maintain atomicity, since there may be bridging or 
> reabstracting conversions happening under the hood.
> 
> -Joe
> 
> Is the following in the ball park of being correct (going back over some old 
> code we have)...
> 
> public struct AtomicBool {
> 
>     private static let bitLocation: UInt32 = 0
>     private static let trueValue: UInt8 = 0x80
>     private static let falseValue: UInt8 = 0x00
> 
>     private let value = UnsafeMutablePointer<UInt8>.allocate(capacity: 1) // 
> TODO - leaking right? How to deal with that in a struct situation...?
>     public var onSet: ((_ old: Bool, _ new: Bool) -> ())?
> 
>     public init(_ intialValue: Bool = false) {
>         value.initialize(to: intialValue ? AtomicBool.trueValue : 
> AtomicBool.falseValue)
>         onSet = nil
>     }
> 
>     public init(_ intialValue: Bool = false, onSet: ((_ old: Bool, _ new: 
> Bool) -> ())?) {
>         value.initialize(to: intialValue ? AtomicBool.trueValue : 
> AtomicBool.falseValue)
>         self.onSet = onSet
>     }
> 
>     public mutating func set(_ newValue: Bool) {
>         _ = getAndSet(newValue)
>     }
> 
>     public mutating func getAndSet(_ newValue: Bool) -> Bool {
>         let oldValue: Bool
>         if newValue {
>             oldValue = 
> Darwin.OSAtomicTestAndSetBarrier(AtomicBool.bitLocation, value)
>         }
>         else {
>             oldValue = 
> Darwin.OSAtomicTestAndClearBarrier(AtomicBool.bitLocation, value)
>         }
> 
>         onSet?(oldValue, newValue)
>         return oldValue
>     }
> 
>     public func get() -> Bool { // TODO - document the lazy "safety" aspect 
> of get
>         return value.pointee != AtomicBool.falseValue
>     }

That looks OK. It might be better to provide an allocate/deallocate or with { 
... } interface instead of burying the allocate call in the initializer since 
the user will need to handle the deallocation of the buffer at some point.

-Joe
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to