PDA

View Full Version : Why QMutex.lock() doesn't return any code?



googie
18th October 2013, 16:34
I wonder why QMutex.lock() (and unlock()) does not return any result code?
pthreads provide return code, wxWidgets provide error codes in their wxMutex (http://docs.wxwidgets.org/trunk/classwx_mutex.html). Why does Qt not do the same? What will happen in Qt app if underlying pthread_* function would fail? What chances are for the application to recover from it?

wysota
18th October 2013, 17:25
One of the reasons might be that the mutex API for Windows does not provide any return code. Besides any of the return codes for wxWidgets mutexes do not make sense with Qt's mutexes.

anda_skoa
18th October 2013, 17:43
Just guessing: those error conditions might not be available on all platforms.

Some of pthread's error conditions also can't happen. For example EINVAL cannot happen because QMutex has always initialized the platform mutex before calling any operations on it.

It seems the only missing error is EAGAIN, when a recursive mutex cannot be further locked because its recursion depth is reached.
But then again needing a recursive mutex is almost always a sign for too complex critical sections, reaching the max recursion depth would be a dead give-away.

Cheers,
_

googie
19th October 2013, 00:30
What about implementations of QMutexPrivate constructor? Code for win:
QMutexPrivate::QMutexPrivate()
{
event = CreateEvent(0, FALSE, FALSE, 0);
if (!event)
qWarning("QMutexData::QMutexData: Cannot create event");
}

Code for unix:
static void report_error(int code, const char *where, const char *what)
{
if (code != 0)
qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
}

QMutexPrivate::QMutexPrivate()
: wakeup(false)
{
report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
qt_initialize_pthread_cond(&cond, "QMutex");
}

Constructor initializes synchronization primitive, then if it failed, just reports it with warning and keeps going:
bool QMutexPrivate::wait(int timeout)
{
report_error(pthread_mutex_lock(&mutex), "QMutex::lock", "mutex lock");
...

Similar code is for Windows. Is that right to just warn about the problem and then execute another functions on it?! Shouldn't the application be aware that there was a problem with the mutex, so it can stop doing what it's doing, maybe retry, or allow any other kind of recovery strategy?

wysota
19th October 2013, 09:20
Read again why a mutex might fail and how many of such siuations apply to QMutex. Furthermore as far as I remember it uses a real mutex only if it detects that another thread is already in the critical section.

googie
19th October 2013, 13:00
Well:
The pthread_mutex_init() function will fail if:
[EAGAIN]
The system lacked the necessary resources (other than memory) to initialise another mutex.
[ENOMEM]
Insufficient memory exists to initialise the mutex.
[EPERM]
The caller does not have the privilege to perform the operation.

[EBUSY]
The implementation has detected an attempt to re-initialise the object referenced by mutex, a previously initialised, but not yet destroyed, mutex.
[EINVAL]
The value specified by attr is invalid.

The EAGAIN seems very much important and capable for some recovery. EPERM looks legit too. I can only guess what are other possible problems like that (not only for lock() method and not only for pthread). What about that?

googie
22nd October 2013, 09:48
I really want to understand, why pthread_mutex_init() results are ignored.

wysota
22nd October 2013, 10:02
I really want to understand, why pthread_mutex_init() results are ignored.

Ask @ digia.