{"id":611,"date":"2007-11-25T16:23:01","date_gmt":"2007-11-25T23:23:01","guid":{"rendered":"http:\/\/www.gubatron.com\/blog\/2007\/11\/25\/pyqt4-using-qmutex-vs-qmutexlocker\/"},"modified":"2007-11-25T16:23:01","modified_gmt":"2007-11-25T23:23:01","slug":"pyqt4-using-qmutex-vs-qmutexlocker","status":"publish","type":"post","link":"https:\/\/www.gubatron.com\/blog\/pyqt4-using-qmutex-vs-qmutexlocker\/","title":{"rendered":"PyQt4: Using QMutex vs QMutexLocker."},"content":{"rendered":"<p>Here&#8217;s some code for my future reference on how to use QMutex or QMutexLocker.<\/p>\n<p>Lessons Learned:<br \/>\n * Use QMutex to protect data, not code. Try not to lock hughe amounts of code within a function with mutex.lock(), mutex.unlock(), if for any reason you forget to release the lock you&#8217;ll be in trouble. Use the mutex directly only when you know what it is that you want to protect concurrent access from.<br \/>\n * When you have a complex function and you don&#8217;t want to worry about what to protect and when to release the lock (on exceptions thrown, before returns,etc), you can create an instance of QMutexLocker and it should release the mutex lock upon destruction&#8230; this takes us to the next lesson<br \/>\n * When using a QMutexLocker, DO NOT make the QMutexLocker an attribute of your class, otherwise, the reference will live after the method finishes and the lock won&#8217;t be released.<\/p>\n<p>Here&#8217;s some code.<\/p>\n<pre>\nfrom PyQt4.Qt import QObject, QMutex, QApplication, QThread, QMutexLocker\nimport sys\n\nclass MutexTestSubject(QObject):\n\t'''\n\tClass that uses a QMutex to synchronize\n        access to its add(),substract() methods.\n\n        This works perfectly fine.\n\t'''\n\tdef __init__(self):\n\t\tQObject.__init__(self)\n\t\tself.MAX_LIMIT = 100\n\t\tself.MIN_LIMIT = 0\n\t\tself.counter = 50\n\t\tself.mutex = QMutex()\n\n\tdef add(self):\n\t\tself.mutex.lock()\n\t\tif self.counter < self.MAX_LIMIT:\n\t\t\tself.counter = self.counter + 1\n\t\tself.mutex.unlock()\n\n\tdef substract(self):\n\t\tself.mutex.lock()\n\t\tif self.counter > self.MIN_LIMIT:\n\t\t\tself.counter = self.counter - 1\n\t\tself.mutex.unlock()\n\n\tdef printStatus(self,thread):\n\t\tprint \"Counter:\",self.counter,\" - Thread:\",id(thread)\n\n\t\tif self.counter > self.MAX_LIMIT+1 or self.counter < self.MIN_LIMIT:\n\t\t\tprint \"Stopping Threads, Max Surpassed, Not Thread Safe. Last Thread:\",id(thread)\n\t\t\tsys.exit()\n\t\n\nclass MutexLockerTestSubject(QObject):\n\t'''\n\tClass that attemps to synchronize thread\n \taccess to its add(),substract() methods with\n\tthe QMutexLocker object.\n\t'''\n\tdef __init__(self):\n\t\tQObject.__init__(self)\n\t\tself.MAX_LIMIT = 100\n\t\tself.MIN_LIMIT = 0\n\t\tself.counter = 50\n\t\tself.mutex = QMutex()\n\n\tdef add(self):\n\t\t#VIP: DO NOT MAKE mutexLocker an attribute of your class.\n\t\t#other wise it won't be destroyed and the lock will never be released.\n\t\tmutexLocker = QMutexLocker(self.mutex)\n\t\tif self.counter < self.MAX_LIMIT:\n\t\t\tself.counter = self.counter + 1\n\n\tdef substract(self):\n\t\tmutexLocker = QMutexLocker(self.mutex)\n\t\tif self.counter > self.MIN_LIMIT:\n\t\t\tself.counter = self.counter - 1\n\n\tdef printStatus(self,thread):\n\t\tprint \"Counter:\",self.counter,\" - Thread:\",id(thread)\n\n\t\tif self.counter > self.MAX_LIMIT+1 or self.counter < self.MIN_LIMIT:\n\t\t\tprint \"Stopping Threads, Max Surpassed, Not Thread Safe. Last Thread:\",id(thread)\n\t\t\tsys.exit()\n\n\nclass AdderWorker(QThread):\n\tdef __init__(self, mutexTestObject):\n\t\tself.mutexTestObject = mutexTestObject\n\t\tQThread.__init__(self)\n\n\tdef run(self):\n\t\twhile(True):\n\t\t\tself.mutexTestObject.add()\n\t\t\tself.mutexTestObject.printStatus(self)\n\nclass SubstractorWorker(QThread):\n\tdef __init__(self, mutexTestObject):\n\t\tself.mutexTestObject = mutexTestObject\n\t\tQThread.__init__(self,mutexTestObject)\n\n\tdef run(self):\n\t\twhile(True):\n\t\t\tself.mutexTestObject.substract()\n\t\t\tself.mutexTestObject.printStatus(self)\n\nif __name__ == \"__main__\":\n\tUSE_MUTEX_LOCKER = True #switch this to use regular mutexes vd QMutexLocker\n\tapp = QApplication(sys.argv)\n\tmutexTestObject = MutexTestSubject() if not USE_MUTEX_LOCKER else MutexLockerTestSubject()\n\n\tadderThread  = AdderWorker(mutexTestObject)\n\tsubstracterThread = SubstractorWorker(mutexTestObject)\n\n\tadderThread.start()\n\tsubstracterThread.start()\n\n\tsys.exit(app.exec_())\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s some code for my future reference on how to use QMutex or QMutexLocker. Lessons Learned: * Use QMutex to protect data, not code. Try not to lock hughe amounts of code within a function with mutex.lock(), mutex.unlock(), if for any reason you forget to release the lock you&#8217;ll be in trouble. Use the mutex [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[15,65,66],"tags":[820],"class_list":["post-611","post","type-post","status-publish","format-standard","hentry","category-code","category-python","category-qt4","tag-python-qt4-pyqt3-mutex-qmutex-qmutexlocker"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5Unzf-9R","jetpack-related-posts":[{"id":650,"url":"https:\/\/www.gubatron.com\/blog\/checking-what-pyqt4-version-youre-running\/","url_meta":{"origin":611,"position":0},"title":"Checking what PyQt4 version you&#8217;re running","author":"gubatron","date":"February 1, 2008","format":false,"excerpt":"This is one of those things I tend to forget >>> PyQt4.Qt.qVersion() '4.3.3'","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":788,"url":"https:\/\/www.gubatron.com\/blog\/blooploader-06-is-hardy-compatible\/","url_meta":{"origin":611,"position":1},"title":"Blooploader 0.6 is Hardy compatible","author":"gubatron","date":"April 26, 2008","format":false,"excerpt":"Blooploader 0.6 running on Hardy. Currently available only via subversion. For our Linux users, you can safely update to Ubuntu Hardy if the one thing holding your breath was compatibility with the Blooploader. Currently we run the Blooploader in Linux from source, you just need to have installed, Qt4, sip4,\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":541,"url":"https:\/\/www.gubatron.com\/blog\/note-about-signals-and-pyqt4\/","url_meta":{"origin":611,"position":2},"title":"Note about Signals and PyQt4.","author":"gubatron","date":"July 9, 2007","format":false,"excerpt":"I keep making the mistake of sending PyQt_PyObjects instead of sending actual Qt4 objects on signals that are defined by Qt like that. Bottom line: If a signal has been defined by Qt, to send Qt objects, just copy and paste it, do not try to override it by exchanging\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":518,"url":"https:\/\/www.gubatron.com\/blog\/creative-qtpyqt-gui-developers-needed\/","url_meta":{"origin":611,"position":3},"title":"Do you dream about coding with Python and Qt4 (PyQt4)? Temboo needs you.","author":"gubatron","date":"May 12, 2007","format":false,"excerpt":"Creative Qt\/PyQt GUI Developers needed About us: Temboo is a New York-based software company. We have developed a new software model which uses a powerful graphical interface to allow non-programmers to quickly build complex workflows enabling disparate databases, web services, and applications to communicate and interact. Think of our technology\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":470,"url":"https:\/\/www.gubatron.com\/blog\/how-to-build-pyqt4-for-windows\/","url_meta":{"origin":611,"position":4},"title":"How to build PyQt4 for Windows","author":"gubatron","date":"February 23, 2007","format":false,"excerpt":"- Make sure you don't have cygwin or C:devkitPromsysbin in your path, or else your make files can end up trying to run the Makefile using 'sh' and all the makefile we're about to use are meant to run from the windows command line. If for some odd reason you\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1946,"url":"https:\/\/www.gubatron.com\/blog\/reviewing-the-nokia-n900-user-and-developer-opinions\/","url_meta":{"origin":611,"position":5},"title":"Reviewing the Nokia N900, User and Developer opinions.","author":"gubatron","date":"July 7, 2010","format":false,"excerpt":"Playing with it from the User Perspective - Virtual keyboard is deactivated by default, not good if you have one hand busy, however I can see why it's this way (the virtual keyboard sucks). When it comes out it covers the entire screen, and the experience with it is not\u2026","rel":"","context":"In &quot;Android&quot;","block_context":{"text":"Android","link":"https:\/\/www.gubatron.com\/blog\/category\/android\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/posts\/611","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/comments?post=611"}],"version-history":[{"count":0,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/posts\/611\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/media?parent=611"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/categories?post=611"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/tags?post=611"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}