Dear Susan,

> Am 20.07.2016 um 14:14 schrieb Susan Cheng <[email protected]>:
> 
> I forgot to reply, a shared value type can capture by multiple closures.
> 
> func twoThreads() -> (Thread, Thread) {
>     var shared_int = 0
>     return (Thread { shared_int = 1 }, Thread { shared_int = 2 })
> }

You are not sharing the value type, but the reference to it (so you share the 
surrounding function context *by reference* or more precisely via *call by 
sharing*). I use an array as example (and synchronous dispatch queues, to get a 
reliable answer), because its value is less „atomic“: 

```swift
var shared_array = [Int]()
var not_shared_array = shared_array
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    var not_shared_array = shared_array
    not_shared_array.append(1)
    print("not shared 1: \(not_shared_array)")
    shared_array.append(2)
    print("shared 2: \(shared_array)")
}

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    var not_shared_array = shared_array
    not_shared_array.append(3)
    print("not shared 3: \(not_shared_array)")
    shared_array.append(4)
    print("shared 4: \(shared_array)")
}

not_shared_array.append(5)
shared_array.append(6)
print("not shared: \(not_shared_array)")
print("shared: \(shared_array)“)

// prints:
// not shared 1: [1]
// shared 2: [2]
// not shared 3: [2, 3]
// shared 4: [2, 4]
// not shared: [5]
// shared: [2, 4, 6]
```

You could do this without closures using a reference type as a wrapper, but you 
still do not share the value instance but the wrapper:

```swift
class Wrapper {
    var shared_array = [Int]()
}

func appendNumber(w: Wrapper, n: Int) {
    w.shared_array.append(n)
}

func appendNumber(var v: [Int], n: Int) {
    v.append(n)
}

let wi = Wrapper(),
    vi = [Int]()

appendNumber(wi, n: 1)
appendNumber(vi, n: 2)
print(wi.shared_array)
print(vi)

// prints:
// [1]
// []
```

All the best
Johannes

> 
> Johannes Neubauer <[email protected]> 於 2016年7月18日星期一 寫道:
> 
> > Am 18.07.2016 um 06:47 schrieb Susan Cheng <[email protected]>:
> >
> > so, you want to propose default == operator but not forbidding all peoples 
> > to custom == operator?
> > Why don't just adding the following function to std library?
> >
> > public func == <T : Equatable>(lhs: T, rhs: T) -> Bool {
> >     var lhs = lhs
> >     var rhs = rhs
> >     return memcmp(&lhs, &rhs, sizeof(T.self)) == 0
> > }
> 
> This does not work, because method parameters are statically dispatched. This 
> function will never be executed for any type, that has a custom equality 
> implementation. So this would not enforce this check upfront. You would need 
> to copy this code to every custom implementation (which can be forgotten). Or 
> you have to implement it like this
> 
> ```swift
> public func isSame(lhs: Any, rhs: Any) -> Bool {
>   // like above in your code
> }
> 
> public func ==(lhs: MyType, rhs: MyType) -> Bool {
>   if isSame(lhs, rhs: rhs) {
>     return true
>   }
>   // do custom behavior
> }
> ```
> 
> > Thread safety can't fixed by std library. Value type only can atomic 
> > compared when additional mutex provided.
> 
> Value types are either on the stack or they are **copied** to the heap (for 
> protocol types with large value types). So, you don’t have any thread safety 
> issues (as they are copied before they are changed in the new thread) as long 
> as you don’t do (or check) anything on a property of a reference type, 
> because the latter has shared **state**.

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to