Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: Igors от Февраль 17, 2016, 05:10



Название: Узнать какая QThread захватила QMutex
Отправлено: Igors от Февраль 17, 2016, 05:10
Добрый день

Не наблюдаю такого метода у QMutex. Можно ли реализовать его самому?

Спасибо


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Igors от Февраль 18, 2016, 08:15
Вот сделал так. Думаю наследование от QMutex неудачно, он для этого явно не предназначен, поэтому агрегатом
Код
C++ (Qt)
#ifndef CMUTEX_H
#define CMUTEX_H
 
#include <QMutex>
#include <QThread>
 
class CMutex {
public:
CMutex( void ) : mOwner(0) {}
 
void Lock( void )
{
mMutex.lock();
mOwner = QThread::currentThread();
}
 
void Unlock( void )
{
mOwner = 0;
mMutex.unlock();
}
 
QThread * GetOwner( void ) const
{
return mOwner;
}
 
private:
QThread * mOwner;
QMutex mMutex;
};
 
#endif // CMUTEX_H
 
Жаль что в Qt нет этого метода  :'(


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Racheengel от Февраль 18, 2016, 10:13
С QMutexLocker не будет работать :(


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Igors от Февраль 18, 2016, 10:18
С QMutexLocker не будет работать :(
Да, и с наследованием тоже, поэтому лучше без него. Ну ничего, это я переживу.

А больше Вас ничего не смущает?  :)


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Racheengel от Февраль 18, 2016, 12:35
Да, и с наследованием тоже, поэтому лучше без него. Ну ничего, это я переживу.

А почему все-таки не наследоваться? Что противоречит? Ведь смысл тут расширить функционал, а не изменить.

А больше Вас ничего не смущает?  :)

Вот это, например:

Код:
void GetOwner( void ) const
{
return mOwner;
}

не скомпилиццо...


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Igors от Февраль 18, 2016, 13:16
Вот это, например:

Код:
void GetOwner( void ) const
{
return mOwner;
}

не скомпилиццо...
То опыска  :) Исправил, спасибо

Но суть не в этом. Я удивлен - ожидал что немедленно укажут на мою безграмотность! Но.. ничего не произошло  :)


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Racheengel от Февраль 18, 2016, 13:31
Я бы, пожалуй, указал еще на то, что QMutex может быть параметризируемым. И дефолтное значение QMutex::RecursionMode = NonRecursive является далеко не всегда оптимальным, часто приходится создавать мутексы с QMutex::Recursive.

Ну и проверка на QThread::isFinished() в геттере, имхо, не помешала бы (например, тред остановился до Unlock - тогда по хорошему надо возращать 0).


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: xokc от Февраль 18, 2016, 16:25
Я удивлен - ожидал что немедленно укажут на мою безграмотность! Но.. ничего не произошло  :)
Подозреваю, между mMutex.lock() и mOwner = QThread::currentThread() текущий поток вполне может стать уже другим.


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Racheengel от Февраль 18, 2016, 16:31
Подозреваю, между mMutex.lock() и mOwner = QThread::currentThread() текущий поток вполне может стать уже другим.

Каким образом? Мутекс то уже залочился. Другие потоки на этом месте стоят и ждут unlock().


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: poru от Февраль 18, 2016, 16:43
А кому нужен метод GetOwner? В прочих участках программы мы всегда будем получать 0. А id владельца только в секции lock. Зачем вообще этот класс?  :)


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: xokc от Февраль 18, 2016, 22:54
Каким образом? Мутекс то уже залочился. Другие потоки на этом месте стоят и ждут unlock().
С чего это всем другим потокам ждать? Ждать будут только те потоки, которые будут пытать сделать lock, всем остальным потокам глубоко всё равно на этот мьютекс. Так что currentThread() в контексте CMutex::lock() в общем случае может не иметь ничего общего с тем потоком, из которого, собственно, и был вызван lock().


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Bepec от Февраль 18, 2016, 22:58
currentThread вроде бы отдаёт id потока, в котором находится объект/исполняется функция.
А другие потоки не могут залочить мутекс пока его не отпустит этот поток.


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Igors от Февраль 19, 2016, 07:00
Общее правило: если есть хоть один "пишущий" (переменная изменяется), то ВСЕ обращения к этой переменной, как по записи, так и по ЧТЕНИЮ) должны быть защищены. В данном случае GetOwner (чтение) не защищено
Код
C++ (Qt)
// Thread 1
if (mutex.GetOwner() == someValue)
.. <- пробой
 
// Thread  2
mOwner = QThread::currentThread();  // в методе CMutex::Lock
 
В точке "пробой" возвращенное значение запросто может быть изменено др ниткой (Thread 2)

Это некорректно (и безграмотно). Тут легко найти "подтверждения". Напр "так вот почему великие "тролли" не сделали этот метод!"  Казалось бы - все, мой жалкий велик никуда не годится  :'(  И можно "опускать занавес"

Или.. мы чего-то не учли?  :)


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Bepec от Февраль 19, 2016, 16:59
Всем просто пофиг на вашу ловушку :D


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Racheengel от Февраль 19, 2016, 19:28
Ждать будут только те потоки, которые будут пытать сделать lock, всем остальным потокам глубоко всё равно на этот мьютекс. Так что currentThread() в контексте CMutex::lock() в общем случае может не иметь ничего общего с тем потоком, из которого, собственно, и был вызван lock().

Правильно, поэтому только поток, который смог сделать lock(), продвинется дальше и вернет себя в currentThread().


Название: Re: Узнать какая QThread захватила QMutex
Отправлено: Igors от Февраль 20, 2016, 12:15
И дефолтное значение QMutex::RecursionMode = NonRecursive является далеко не всегда оптимальным, часто приходится создавать мутексы с QMutex::Recursive.
Как ни странно, это имеет прямое отношение к теме, гораздо большее чем к дизайну класса вообще. Легко можно сделать CMutex рекурсивным самому (оставив mMutex нерекурсивным).

Есть масса часов показывающих точное время только 2 раза в сутки. Оказывается, они не так уж бесполезны :)

Всем просто пофиг на вашу ловушку :D
За всех не расписывайтесь, а Вам пофиг - так нечего тут шуршать  :)