I’m trying to decide whether to make a method a shared or instance method. It “feels” like it should be a shared method but I am concerned about thread safety. This is very technical but are there any caveats to calling shared methods from multiple threads vs having the method as an instance method?
It’s like any other method. If you want to make sure it is thread-safe, be sure to use local variables, not class or global properties, to store state. Use Semaphores to keep concurrent methods from modifying data that should not be modified concurrently.
The easiest way to avoid problems with threads is instance methods.
A shared method can be fine with threads.
It can use global variables.
Of course you have to think about not touching GUI.
And think about the method called on two threads at the same time.
But otherwise, continue!
Thanks guys - makes sense. I feel more confident using the shared method approach. Cheers.
Keep in mind that you can’t call any Xojo methods. That includes creating objects.
The best you can hope for is setting properties for things like Integers, Booleans and Memoryblocks.
Do you mean the Xojo namespaced ones? Is that just from shared methods running in a thread?
Well… It depends on what you mean by thread-safe. If you’re talking about Xojo threads, then no, what I’m describing does not apply. If you’re talking about Pre-emptive threads calling from outside of the xojo framework then it definitely does. That’s usually what people are talking about when they say “thread-safe”.
Ah. I’m talking about calling a shared method on a class from multiple Xojo threads from within a Xojo app.
Each call gets its own copy of local variables. Hence the recommendation to use locals for state. Global variables may result in a collision.
Global variables are the bane of multithreaded stuff and usually mean you need mutex’s or semaphores around them
ESP preemptive threads
Xojo threads not so much as they can never be in a some of the weird states you can get into with preemptive threads
/ie thread A and B want to increment global var FOO (FOO = FOO + 1)
and FOO starts out at 0
thread A reads FOO (reads 0) thread A increments its local temp copy of FOO (tmp is now 1) THREAD SWITCH thread B reads FOO (reads 0) thread B increments its local temp copy of FOO (tmp is now 1) thread B saves temp into FOO (FOO = 1) THREAD SWITCH thread A saves temp into FOO (FOO = 1)
and FOO is not 2 but 1 - and you have a really impossible bug to track down because the chances you will ever reproduce it are pretty close to 0 (and one reason I dont think preemptive threads are ever going to happen as they are just too damned hard to reason about)
But even in Xojo where these preemptive thread switches cant happen like this you may still need a mutex or semaphore around them
Really depends on what the global is for
I pass all the needed parameters to my methods.
If one thread calls up a Method with it’s parameters and loops around for a while, then a second thread runs and calls the same Method with its different parameters, and loops around, will the second thread’s parameters clobber the first thread’s parameters?
[quote=440798:@David Cox]I pass all the needed parameters to my methods.
If one thread calls up a Method with it’s parameters and loops around for a while, then a second thread runs and calls the same Method with its different parameters, and loops around, will the second thread’s parameters clobber the first thread’s parameters?[/quote]
No, they are completely separate. Each thread has its own stack and all parameters and a method’s local variable are on the thread’s stack.
It would be pretty useless if it didn’t work that way; this is what re-entrancy does.
Also, there is no functional difference between a parameter variable and a local variable declared within the method.