Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / QT

Having a Global named Mutex in Qt 5.2

4.79/5 (10 votes)
22 Apr 2014CPOL3 min read 23.7K  
Qt grew up to be a quite adult framework, but is still missing a global named Mutex - Something I fixed with a little trick.

Introduction

Qt grew to a quite mature framework over the past few years, and I dare to say that it probably can keep up with "mighty" frameworks like .NET or Java from a functional point of view. Of course, there is stuff like the Entity Framework for .NET, but with Qt 5.2, a developer gets a solid Framework base to build up great applications on. However, there is still one thing missing from Qt 5.2: You can have a QMutex, you have Semaphores, but you don't have a global named mutex.

Background

Now, why would you need a global Mutex anyways? And why would you want to give it a name?
I came across the situation that I needed a global named Mutex just recently, and because it makes a great example of a Use Case where one needs a global named Mutex, I decided to show it off:

Image 1

The first approach would've worked fine with the usual QMutex only - A Process with a Reader and a Writer inside (important: Reader and Writer live in different threads), both of them accessing a common data storage (A Directory, to be exact, but it could also be a shared Memory, a single file - You get my point).

But what happens if we extend this scenario? Let's say there is still just one data storage, but 4 threads accessing it from two different processes:

Image 2

This leads us to the problem that QMutex is only accessible within a single process and not globally to every process on the computer. That is where the global Mutex is needed: to synchronize access to a common resource over multiple threads and processes.

I did my bit of Googlin' but haven't found a named Mutex class, but plenty of suggestions on what one can do to implement their own global named QMutex. What I found to be the easiest and most durable solution is to encapsule the QSharedMemory class with a custom wrapper.
QSharedMemory is a class of Qt which allows multiple processes to access the same bit of memory, and it has also its own Mutex to lock access to the shared memory before reading from or writing to it.

Using the Code

The class I came up with is pretty, small, and simple. All it does is encapsulate an instance of QSharedMemory and only provide access to the Lock() and Unlock() methods:

C++
/// Description
/// =========================================
/// QtGlobalMutex provides the functionality of a global named Mutex
/// which is missing in the current version of Qt (Qt 5.2)
///
/// Copyright notice
/// ========================================
/// Copyright (C) 2014, Marco Bertschi
/// Available under the terms of the CodeProject Open License (CPOL)
#ifndef QTGLOBALMUTEX_H
#define QTGLOBALMUTEX_H

#include <QObject>
#include <QString>
#include <QSharedMemory>

class QtGlobalMutex: public QObject{
   Q_OBJECT
private:
   QSharedMemory* sharedMemory; /*!< Used to provide the locking and unlocking 
                                     implementation*/
public:
   QtGlobalMutex(QString name);
   ~QtGlobalMutex();

   void Lock();
   void Unlock();

};

#endif //QTGLOBALMUTEX_H

The implementation of the code is equally simple, the constructor just initializes a heap pointer to a QSharedMemory object, passing on the Mutex's name as argument to the QSharedMemory:

C++
//+------------------------------------------------------------------------------------
//! Initializes a new instance of a QtGlobalMutex.
//! The name of the Mutex is expected as parameter.
//+------------------------------------------------------------------------------------
//| Arguments:
//! name      QString [in]     Name of the Mutex, used to identify it globally
//+------------------------------------------------------------------------------------
QtGlobalMutex::QtGlobalMutex(QString name){
   sharedMemory = new QSharedMemory(name);
}

Did I just initialize a heap pointer? Yes. What do we do with heap pointers? Right! We make sure that they are deleted correctly:

C++
//+------------------------------------------------------------------------------------
//! Uninitializes an instance of a QtGlobalMutex.
//+------------------------------------------------------------------------------------
//| Arguments:
//! - N/A -
//+------------------------------------------------------------------------------------
QtGlobalMutex::~QtGlobalMutex(){
   delete sharedMemory;
}

The Lock() and Unlock() methods aren't really worth talking about since all that they do is call the corresponding method on the QSharedMemory.

Points of Interest

I'm still kinda puzzled why Qt doesn't offer a global named Mutex, especially since making one on your own is a 15 minutes task. I'll post an update if I ever find out, so far I'm doing good with my homemade version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)