[SOLVED] Thread safe global variables
-
Ok, I just realized you're not returning by reference, so you might get away with this:
@
void get(int& param)
{
QMutexLocker(mMutex);
param = mVar;
}int get()
{
int temp;
get(temp);
return temp;
}
@
or even that:
@
int get()
{
int temp;
{
QMutexLocker(mMutex);
temp = mVar;
}
return temp;
}
@
Just be careful not to do that:
@
int& get()
{
int temp;
get(temp);
return temp;
}
@ -
[quote author="Krzysztof Kawa" date="1361557626"]
@int get()
{
int temp;
{
QMutexLocker(mMutex);
temp = mVar;
}
return temp;
}@
[/quote]Are the braces required in your example above? I think the following should work as well:
@QString get()
{
QString temp;
QMutexLocker locker(&mMutex);
temp = mVar;
return temp;
}
// OR
QString get()
{
QString temp;mMutex.lock() temp = mVar; mMutex.unlock(); return temp;
}
@ -
The second variant (with the lock/unlock) sure.
The first one.. hm, it might be the case but to be honest I'm just not sure and don't want to mislead you.I recently saw "this great talk on atomics, locks etc.":http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 and it just brainwashed me. I see traps everywhere :P
-
[quote author="Krzysztof Kawa" date="1361560263"]The second variant (with the lock/unlock) sure.
The first one.. hm, it might be the case but to be honest I'm just not sure and don't want to mislead you.I recently saw "this great talk on atomics, locks etc.":http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 and it just brainwashed me. I see traps everywhere :P[/quote]
Haha right, it's like that when it comes to threads. Thanks a lot you really helped me here.
-
Just one more thing... I guess that the compiler will not try to optimize anything in the examples above and end up with not thread safe code?
-
Oh it will optimize the s*** out of it with things like RVO, OoOE and whatnot, but it's a good thing and a lot of people are paid a lot of money for it to stay safe and you don't need to think about it when you write threading code. The guarantee is nothing will escape the guarded region, otherwise locking/unlocking wouldn't make much sense. So don't be afraid of the compiler, just stay frosty ;)
-
"VoidRealms":http://www.youtube.com/watch?v=yazMHbIew0Q
Just look at his tutorials (previous ones i think...)
Hope it helps... -
All those QThread discussions seem to lead to just different approaches to the same old problem - how to abstract away the low level threading stuff. I mean - what we really want to do is to make an asynchronous call and do something when the result is available. We shouldn't be bothered by threads, mutexes, locks and race conditions. Multi-threaded algorithms are hard enough on their own.
That's what the industry has slowly started to realize lately and that's why there's been change in threading APis approach. Examples are PPL, AMP, QtConcurrent and even the new std c++11 threading api.
In Qt it was an evolution from QThread to QThreadPool to QtConcurrent.
Personally whenever I can I try to stick to basic QtConncurrent::run or QtConcurrent::map etc and just wait for the result with QFuture<>::waitForFinished() or better yet - emit a finished signal when the work is done and react to it in a slot. This way the code becomes simpler, more semantic and really about the algorithm it performs and not about the underlying machinery. I know this is disputable, but I believe threading is done right when there are no QThreads around at all and as little threading primitives (like mutexes or atomics) as possible.
-
I don't think that "threading stuff" is low-level. Race conditions are part of the (high-level) system that you build, you will never be able to push them away completely.
-
When you are working with a complex, parallel algorithm the "threading stuff" indeed becomes low level. Of course you can go lower and lower right down to the processor instructions. That's actually one of the key strengths of C++, but that's not my point. What I'm saying is that threading part shouldn't take 60% of the code. It should be 5% or 2% - one or two lines here and there, or a single keyword (like in some of the AMP constructs).
You might be right that we'll never get rid of the complexities entirely, but you know - somebody said that we'll never need more that 64k of RAM and look what happened :)
-
Yes, there is actually no real need for user space software developers to use fences etc. (and most of them probably never heard of them), but for kernel module or driver developers.
I think the main question is, how much do you want to have done by the compiler - should it perform most of the multi-threading synchronization things itself by analysing your code.
The next question is: is the current approach to write multi-threaded apps actually a good way to do it? Is the old "here is my imperative code, now execute it" way the right way? I don't think so. There is a huge lack in visibility of what the code that you write actually does. Prove me wrong, but neither the language(s) nor the software tools are good enough to manage writing multi-threaded applications in a way where you have a good overview of what is really going on.
The EDA tools that hardware developers use are much better, but who wants to spend 1xxxxx for good software development tools, when the whole world wants free software.
If you know great tools for multi-threaded programming, please tell me. ;)