Results 1 to 12 of 12

Thread: local static QMutex

  1. #1
    Join Date
    Feb 2011
    Posts
    354
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Windows
    Thanks
    17
    Thanked 27 Times in 24 Posts

    Default local static QMutex

    Hello, could somebody answer me if it is safe to use static QMutex on the stack of the function that is called by several threads (see the same code below). Static variables are created only once, but I'm afraid, perhaps, another thread may try to use it when it is not yet created.

    Qt Code:
    1. // safe or not?
    2. void testFunc()
    3. {
    4. static QMutex mutex;
    5. mutex.lock();
    6. // access shared resource
    7. mutex.unlock();
    8. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by mentalmushroom; 23rd January 2012 at 17:43. Reason: incorrect question

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: static QMutex on the stack

    Quote Originally Posted by mentalmushroom View Post
    if it is safe to use static QMutex on the stack
    It is not safe because such things don't exist. Static variables are not allocated on the stack. Don't mix "stack" and "local" variables.

    By the way, mutexes should be used to protect data, not code. Yours protects code.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Feb 2011
    Posts
    354
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Windows
    Thanks
    17
    Thanked 27 Times in 24 Posts

    Default Re: static QMutex on the stack

    Indeed static variables are not allocated on the stack, otherwise they would be lost when function returns. Sorry, my question was incorrect, so I'll ask it different: is it safe to use local static QMutex instance?
    Also could you, please, explain what did you mean saying
    By the way, mutexes should be used to protect data, not code. Yours protects code.
    Yes, mutex protects the data, but we protect it from the code, don't we? Here is more complete sample. Do you find it wrong?

    Qt Code:
    1. QMutex mutex;
    2. bool sharedBoolVariable;
    3.  
    4. void setValueOfSharedResource(bool newValue)
    5. {
    6. // protect the shared data
    7. mutex.lock();
    8. sharedBoolVariable = newValue;
    9. mutex.unlock();
    10. }
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: static QMutex on the stack

    Quote Originally Posted by mentalmushroom View Post
    is it safe to use local static QMutex instance?
    I don't know, probably not, however it doesn't make much sense to do so anyway.

    Also could you, please, explain what did you mean saying Yes, mutex protects the data, but we protect it from the code, don't we? Here is more complete sample. Do you find it wrong?
    You are protecting code (the function) and not the data. If the data is shared, there are at least two places where you access it from thus having a local mutex (static or not) doesn't make sense. Your last snippet is better (however we only see one function using it) and is not prone to the problem you stated (since it is initialized before the program is launched).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Feb 2011
    Posts
    354
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Windows
    Thanks
    17
    Thanked 27 Times in 24 Posts

    Default Re: static QMutex on the stack

    You are protecting code (the function) and not the data. If the data is shared, there are at least two places where you access it from thus having a local mutex (static or not) doesn't make sense. Your last snippet is better (however we only see one function using it) and is not prone to the problem you stated (since it is initialized before the program is launched).
    One function may be called by several different threads, therefore the mutex is used: it protects sharedBoolVariable from being written to at the same time. In the second sample I didn't use local mutex (it was the different question), although, it is often convenient to use static local QMutex in such a case. I've noticed this approach in the code of another more experienced programmer, but it appeared suspicious to me, so I wanted to clear it up.

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: static QMutex on the stack

    Quote Originally Posted by mentalmushroom View Post
    One function may be called by several different threads
    Exactly Thus you are protecting the function and not the variable. Somehow you don't care that one actually has to READ the variable somewhere.

    it is often convenient to use static local QMutex in such a case. I've noticed this approach in the code of another more experienced programmer, but it appeared suspicious to me, so I wanted to clear it up.
    In the first code you posted the use is incorrect. It's a stupid shortcut of a lazy programmer who didn't want to do it properly. It protects access to this method and to this method only.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Feb 2011
    Posts
    354
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Windows
    Thanks
    17
    Thanked 27 Times in 24 Posts

    Default Re: static QMutex on the stack

    Exactly Thus you are protecting the function and not the variable. Somehow you don't care that one actually has to READ the variable somewhere.
    Ok, I know that, and I am not going to fall into a dispute about it (just wanted to be sure I understand you right). However, sometimes (rarely) it is not needed to read anything: that was just a theoretic sample, it could be protection for writing a log when you don't like text from different functions to be mixed or adding/removing thread from the list when you simply don't use that list anywhere else or some kind of a wrapper for not reenterant function.

    Thank you for paying me attention, Master of Zen

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: static QMutex on the stack

    Quote Originally Posted by mentalmushroom View Post
    However, sometimes (rarely) it is not needed to read anything
    What's the point of setting something if nobody cares about it?

    it could be protection for writing a log when you don't like text from different functions to be mixed
    You need to setup the log first somewhere.

    or adding/removing thread from the list
    If you have a single function that both adds and removes from the list then sure however this is not very convinient. Still you are protecting code and not data and that's breaking a primary rule of using critical sections.

    some kind of a wrapper for not reenterant function.
    Again, protecting code instead of data that makes the function not reentrant. Functions are not inherently reentrant. It's the use of data inside them that makes them non reentrant. And by the way, reentrancy is about accessing the same function twice from the same thread so mutexes can't fix reentrancy problems.

    Here's an example of a non reentrant function:

    Qt Code:
    1. char *toUpper(char *txt) {
    2. static char buf[256];
    3. char *ptr = txt;
    4. char *bufPtr = buf;
    5. while(ptr) {
    6. *(bufPtr++) = toUpper(*(ptr++));
    7. }
    8. *bufPtr = 0;
    9. return buf;
    10. }
    To copy to clipboard, switch view to plain text mode 

    This call is not allowed with it:

    Qt Code:
    1. char *result = toUpper(toUpper("xyz"));
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. #9
    Join Date
    Feb 2011
    Posts
    354
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Windows
    Thanks
    17
    Thanked 27 Times in 24 Posts

    Default Re: static QMutex on the stack

    I decided to create a sample application where the local static QMutex is used. Mutex is used in the print function. If I don't use it, text is printed in a wrong order. It seems to work fine, except it, perhaps, violates some rule you mentioned. I didn't notice any bugs or any other problems so far, do you think this code is incorrect? Honestly, I don't know the rule you are talking about. Where can I read it?

    Qt Code:
    1. #include <QtCore/QCoreApplication>
    2. #include <QThread>
    3. #include <QMetaType>
    4. #include <QMutex>
    5. #include <iostream>
    6.  
    7. void print(const QString &message)
    8. {
    9. using namespace std;
    10.  
    11. static QMutex mutex;
    12. mutex.lock(); // if we run it without mutex, lines may be mixed
    13. cout << QThread::currentThreadId() << " " << qPrintable(message) << endl;
    14. mutex.unlock();
    15. }
    16.  
    17. class Printer: public QObject
    18. {
    19. Q_OBJECT
    20.  
    21. public slots:
    22. void startPrinting()
    23. {
    24. for (int i = 0; i < 1000; ++i)
    25. {
    26. // perform some processing...
    27. // ...
    28.  
    29. // print something on the screen/to the log/whatever
    30. print(QString("i = %1").arg(i));
    31. }
    32.  
    33. emit finished();
    34. }
    35.  
    36. signals:
    37. void finished();
    38. };
    39.  
    40. //Q_DECLARE_METATYPE(Printer*)
    41.  
    42. int main(int argc, char *argv[])
    43. {
    44. QCoreApplication a(argc, argv);
    45.  
    46. QThread *t1 = new QThread;
    47. Printer *printer1 = new Printer;
    48. printer1->moveToThread(t1);
    49.  
    50. QThread *t2 = new QThread;
    51. Printer *printer2 = new Printer;
    52. printer2->moveToThread(t2);
    53.  
    54. QObject::connect(t1, SIGNAL(started()), printer1, SLOT(startPrinting()));
    55. QObject::connect(printer1, SIGNAL(finished()), t1, SLOT(quit()));
    56. QObject::connect(t1, SIGNAL(finished()), printer1, SLOT(deleteLater()));
    57. QObject::connect(t1, SIGNAL(finished()), t1, SLOT(deleteLater()));
    58.  
    59. QObject::connect(t2, SIGNAL(started()), printer2, SLOT(startPrinting()));
    60. QObject::connect(printer2, SIGNAL(finished()), t2, SLOT(quit()));
    61. QObject::connect(t2, SIGNAL(finished()), t2, SLOT(deleteLater()));
    62. QObject::connect(t2, SIGNAL(finished()), printer2, SLOT(deleteLater()));
    63.  
    64. t1->start();
    65. t2->start();
    66.  
    67. return a.exec();
    68. }
    69.  
    70. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: static QMutex on the stack

    This will seem to work fine too however is completely incorrect and some day when you least expect it will explode in your face:

    Qt Code:
    1. QString x = "abc";
    2. printf("%s\n", x.toLocal8Bit().constData());
    To copy to clipboard, switch view to plain text mode 

    Sorry, it's no argument for me that something "works".

    By the way, this will also "works" most of the time:
    Qt Code:
    1. int x, y; // uninitialized
    2. int z = x/y;
    To copy to clipboard, switch view to plain text mode 
    Last edited by wysota; 25th January 2012 at 09:21.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #11
    Join Date
    Feb 2011
    Posts
    354
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Windows
    Thanks
    17
    Thanked 27 Times in 24 Posts

    Default Re: static QMutex on the stack

    This will seem to work fine too however is completely incorrect and some day when you least expect it will explode in your face
    Absolutely agree, I've already experienced such situations. But here I don't see any reason for that, except local static QMutex that I am not sure work correct.

    QString x = "abc";
    printf("%s\n", x.toLocal8Bit().constData());
    What is wrong with this code (just curious)?

  12. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: static QMutex on the stack

    Quote Originally Posted by mentalmushroom View Post
    But here I don't see any reason for that, except local static QMutex that I am not sure work correct.
    You are breaking rules. When you do that, it's "boo" and not "yay". Regardless if something works or not. If you (or rather someone else) ever need to refactor your code, it is very likely you will miss the mutex declaration inside the print function.

    What is wrong with this code (just curious)?
    Well... maybe this is not that much incorrect as you will get away with it with modern compilers but in general QByteArray created by toLocal8Bit() is a temporary variable that might get deleted before you use the data pointer exposed by constData(). However this is certainly incorrect:
    Qt Code:
    1. const char * dat = x.toLocal8Bit().constData();
    2. printf("%s\n", dat);
    To copy to clipboard, switch view to plain text mode 

    Nevertheless many people use it and claim it to work. It will work most of the time because there is a good chance nothing overwrites the stack based byte array object right after it was deleted (however if your process context switches out between those two lines and registers are dumped to stack, it will be overwritten) and a slightly less chance that the private component allocated on the heap will not be overwritten too.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. static QMutex
    By mhoover in forum Qt Programming
    Replies: 7
    Last Post: 8th August 2014, 05:39
  2. QMutex QMutex::Recursive is not a type name
    By Qiieha in forum Qt Programming
    Replies: 2
    Last Post: 9th May 2011, 14:01
  3. Using a QMutex as a static class member
    By emostar in forum Qt Programming
    Replies: 2
    Last Post: 15th June 2009, 13:48
  4. QMutex
    By weixj2003ld in forum Qt Programming
    Replies: 6
    Last Post: 14th April 2009, 22:32
  5. New to QMutex
    By durbrak in forum Qt Programming
    Replies: 3
    Last Post: 12th March 2009, 21:16

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.