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:
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:
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:
#ifndef QTGLOBALMUTEX_H
#define QTGLOBALMUTEX_H
#include <QObject>
#include <QString>
#include <QSharedMemory>
class QtGlobalMutex: public QObject{
Q_OBJECT
private:
QSharedMemory* sharedMemory;
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
:
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:
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.