2

I am trying to translate some sample code from objective-c into swift!

I got it all working except for the multithreading part which is cruical to this simulation.

For some reason when I start using multiple threads it has access errors. Specefically when getting or setting things from the array.

This class is instanced inside of a static class.

var screenWidthi:Int = 0
var screenHeighti:Int = 0
var poolWidthi:Int = 0
var poolHeighti:Int = 0

var rippleSource:[GLfloat] = []
var rippleDest:[GLfloat] = []

func update()
{
        let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

        dispatch_apply(Int(poolHeighti), queue, {(y: size_t) -> Void in
        //for y in 0..<poolHeighti
        //{
            let pw = self.poolWidthi
            for x in 1..<(pw - 1)
            {
                let ai:Int = (y    ) * (pw + 2) + x + 1
                let bi:Int = (y + 2) * (pw + 2) + x + 1
                let ci:Int = (y + 1) * (pw + 2) + x
                let di:Int = (y + 1) * (pw + 2) + x + 2
                let me:Int = (y + 1) * (pw + 2) + x + 1

                let a = self.rippleSource[ai]
                let b = self.rippleSource[bi]
                let c = self.rippleSource[ci]
                let d = self.rippleSource[di]

                var result = (a + b + c + d) / 2.0 - self.rippleDest[me]
                result -= result / 32.0

                self.rippleDest[me] = result
            }
        }
        )
}

It is important to note that there is also another loop that should run on a different thread right after this one, it acesses the same arrays. That being said it will still bad acess without having the 2nd in another thread so I feel that it is irrelivant to show.

If you could please tell me what is going on that causes this crash to happen at randomish times rather then the first time.

If you want reference here is what it was like in objective c

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_apply(poolHeight, queue, ^(size_t y) {
        for (int x=0; x<poolWidth; x++)
        {
            float a = rippleSource[(y)*(poolWidth+2) + x+1];
            float b = rippleSource[(y+2)*(poolWidth+2) + x+1];
            float c = rippleSource[(y+1)*(poolWidth+2) + x];
            float d = rippleSource[(y+1)*(poolWidth+2) + x+2];

            float result = (a + b + c + d)/2.f - rippleDest[(y+1)*(poolWidth+2) + x+1];

            result -= result/32.f;

            rippleDest[(y+1)*(poolWidth+2) + x+1] = result;
        }            
    });

How do you ensure that variables are able to be accessed from different threads? How about static members?

I only no how to print out the call stack before the app crashes, however after, the only way I know to get to the call stack is to look at the threads. Let me know if there is a different way I should do this. enter image description here

NOTE: I noticed something wierd. I put a print statement in each loop so I could see what x and y coordinate it was processing to see if the crash was consistant. Obiously that brought the fps down to well under 1 fps, however I did notice it has yet to crash. The program is running perfect so far without any bad acess just at under 1 fps.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
J.Doe
  • 1,502
  • 13
  • 47

1 Answers1

3

The Apple code is using a C-style array, these are "thread safe" when used appropriately - as the Apple code does.

Swift, and Objective-C, arrays are not thread-safe and this is the cause of your issues. You need to implement some form of access control to the array.

A simple method is to associate a GCD sequential queue with each array, then to write to the array dispatch async to this queue, and to read dispatch sync. This is simple but reduces concurrency, to make it better read Mike Ash. For Swift code

Mike Ash is good if you need to understand the issues, and for Swift code you and look at this question - read all the answers and comments.

HTH

Community
  • 1
  • 1
CRD
  • 52,522
  • 5
  • 70
  • 86
  • Thankyou that makes a lot of sense! It cant explain the anomaly that I put at the bottom of the question but that is probably just an anomaly, I need to run it much faster then 0.5 fps. I saw some documentation (https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html) saying NSArrays are thread safe is that the same in swift? – J.Doe Sep 04 '16 at 16:51
  • Also if I had a thread safe array as a static method in a class would it still be thread safe? – J.Doe Sep 04 '16 at 16:52
  • In general an immutable type/value should be thread safe, e.g. `NSArray` or `let v = array value`. Thread safety should not be affected by the use of static methods. You probably should research what makes something thread safe or not, understanding that will answer questions like these. – CRD Sep 04 '16 at 17:05
  • As to your anomaly, it isn't. You changed the execution time of your individual concurrent threads by adding the printing, you may have introduced hidden locking/synchronisation (inside print). Thread safety is about the random interactions between actions in seperate unsynchronised threads, you've changed what those threads are doing... Time to do that research! – CRD Sep 04 '16 at 17:13
  • Just downloaded all the wwdic talks on concurrent programming from 2011 to present :) thanks much! – J.Doe Sep 04 '16 at 17:32