I've run in a hard to track craskh. After some investigation, I think it is related to the use of inout parameter in a thread.
I'll try to explain:
class myClass : NSObject {
var aVar : aStruct
func myFunc(param: inout aStruct) {
}
func calling() {
myFunc(param: &aVar)
}
}
When I call this func from another thread, I get random crashes (BAD_ACCESS).
I understand it is not safe to pass address in a thread.
So I try to change like this:
func calling() {
var localVar = aVar
myFunc(param: &localVar)
aVar = localVar
}
That seems to solve the crash, but is that a correct implementation ?
So, is iy thread safe to call
myFunc(param: &localVar)
if localVar is declared in the function ?
This is a serious limit to the use of inout (be careful if the func is to be called from another thread) and I find it really poorly documented (I've found no reference to this in Swift language). Is it detailed somewhere ?
Edited : Note. I feel the crash are much more frequent after I switched to Swit 3 and 4. Is there any reason for that or just an impression ?
The thing about return values was part of Quinn's general advice, and doesn't help much with your case. In general, if a value is being returned in an inout parameter (a use-case in you'll find in the Cocoa APIs, for example, though not very commonly), and if there's a chance that the inout references are being passed across thread boundaries, then returning multiple values, as a direct function result instead, would limit the possibility of thread-unsafety regarding that returned value. However, if the returned value is then assigned to a mutable variable that itself is accessed by multiple threads (your case, sort of), then that is a second cause of unsafety, and the strategy doesn't help.
In your case, the larger cause of the problem is that you're calling a function (the "calling ()" function), which has global side-effects. The best way to solve the problem is to eliminate the side-effects. IOW, delete the "aVar" property. Obviously, we can't tell if there's an alternate approach that would let you do that, because your sample code is too minimal.
A second approach would be to ensure that the function is called on a single, pre-determined thread, such as the main thread, or equivalently the main queue, or a serial queue. That means your multi-threaded code would have to hop between threads, which could be a pretty big change to the code.
Or, you can simply use a lock to protect access the othe "aVar" property. This doesn't obviously require any serious code redesign, except you have to ensure that there are no potential deadlock.