Russian Qt Forum
Ноябрь 22, 2024, 22:33 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: (РЕШЕНО) QWaitCondition::wait() в разных версиях  (Прочитано 10577 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« : Ноябрь 18, 2014, 12:45 »

Проект из-за требований совместимости продолжается на Qt 4.7. В описании QWaitCondition::wait( QMutex*, ... ) четко написано

Цитировать
If mutex is not in a locked state, this function returns immediately.

То есть, подразумевается нормальный возврат. Вместо этого, если мутекс не залочен, то падает по assert (там внутри сразу простая проверка на owner нити, а у нелоченного мутекса owner == 0).

Вопрос - в более новых версиях Qt как? На незалоченном мутексе QWaitCondition::wait() тоже будет падать, или всё-таки, как по описаню, проскочит и вернет false (кстати, про возврат в описании для этого случая ничего не сказано)? У кого последние версии Qt, плз, посмотрите в исходники.
« Последнее редактирование: Ноябрь 19, 2014, 14:56 от Гурман » Записан

2^7-1 == 127, задумайтесь...
vulko
Гость
« Ответ #1 : Ноябрь 18, 2014, 14:16 »

Цитировать
bool QWaitCondition::wait ( QMutex * mutex, unsigned long time = ULONG_MAX )

Releases the locked mutex and waits on the wait condition. The mutex must be initially locked by the calling thread. If mutex is not in a locked state, this function returns immediately. If mutex is a recursive mutex, this function returns immediately. The mutex will be unlocked, and the calling thread will block until either of these conditions is met:

Another thread signals it using wakeOne() or wakeAll(). This function will return true in this case.
time milliseconds has elapsed. If time is ULONG_MAX (the default), then the wait will never timeout (the event must be signalled). This function will return false if the wait timed out.
The mutex will be returned to the same locked state. This function is provided to allow the atomic transition from the locked state to the wait state.

qt 4.8.5, linux.
мьютекс не лочу, отлично работает.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Ноябрь 18, 2014, 18:51 »

Ассыстент 5.3.2
Цитировать
bool QWaitCondition::wait(QMutex * lockedMutex, unsigned long time = ULONG_MAX)
Releases the lockedMutex and waits on the wait condition. The lockedMutex must be initially locked by the calling thread. If lockedMutex is not in a locked state, the behavior is undefined.

И без разницы падает или нет - делать так нет смысла. Возможно Вы хотите написать что-то типа
Код
C++ (Qt)
if (CheckSomething())
condition.wait(&mutex);

Но это не будет работать правильно если мутекс не залочен
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #3 : Ноябрь 18, 2014, 21:49 »

Ассыстент 5.3.2
Цитировать
bool QWaitCondition::wait(QMutex * lockedMutex, unsigned long time = ULONG_MAX)
Releases the lockedMutex and waits on the wait condition. The lockedMutex must be initially locked by the calling thread. If lockedMutex is not in a locked state, the behavior is undefined.

И без разницы падает или нет - делать так нет смысла. Возможно Вы хотите написать что-то типа
Код
C++ (Qt)
if (CheckSomething())
condition.wait(&mutex);

Но это не будет работать правильно если мутекс не залочен

Нет, я хотел написать

Код:
if( ! condition.wait(&mutex) )  // по описанию 4.7 должно быть false, если мутекс не залочен, но тут падает
    mutex.lock();

То есть, если мутекс не был залочен, то его надо залочить. А если был, то ждать - при освобождении перед выходом wait() залочит его сам, в 4.7 так и работает, и это описано. Кстати, в 5.3 тоже так? При выходе из wait(&mutex), mutex будет в залоченном состоянии?
Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #4 : Ноябрь 18, 2014, 22:03 »

Вы не правильно представляете работу условных переменных.
Смысл их в том, что вы лочите мутекс, проверяете доступность ресурса и если ресурс не доступен, то уходите на wait. Он разлочивает мутекс (для того чтобы другие нити могли его заполнить/сделать доступным) и усыпляет нить.
Когда происходит побудка, то нить просыпается в wait, который лочит мутекс и завершается. Мы может при залоченном мутексе опять проверить ресурс на доступность.

На форуме не раз поднималась тепа по услоаным переменным, в которых детально все говорилось.
« Последнее редактирование: Ноябрь 18, 2014, 22:06 от Old » Записан
vulko
Гость
« Ответ #5 : Ноябрь 18, 2014, 22:20 »

Вы не правильно представляете работу условных переменных.
Смысл их в том, что вы лочите мутекс, проверяете доступность ресурса и если ресурс не доступен, то уходите на wait. Он разлочивает мутекс (для того чтобы другие нити могли его заполнить/сделать доступным) и усыпляет нить.
Когда происходит побудка, то нить просыпается в wait, который лочит мутекс и завершается. Мы может при залоченном мутексе опять проверить ресурс на доступность.

На форуме не раз поднималась тепа по услоаным переменным, в которых детально все говорилось.

Если мьютекс отдельный для CV, то можно его и не лочить. Я именно так и делаю. Для приостановки потока самое оно.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #6 : Ноябрь 18, 2014, 22:54 »

Я не вижу смысла в условных переменных без защищаемого ресурса и связанного с ним мутекса.
Записан
vulko
Гость
« Ответ #7 : Ноябрь 18, 2014, 23:14 »

Я не вижу смысла в условных переменных без защищаемого ресурса и связанного с ним мутекса.

Например контроль работы потока. Приостановить и продолжить работу.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #8 : Ноябрь 18, 2014, 23:18 »

Например контроль работы потока. Приостановить и продолжить работу.
Не очень понятно, что это за контроль? Для чего он нужен?
И я бы все равно сделал переменную bool pause, защитил ее мутексом и использовал ее для организации приостановки - это и был бы защищаемый ресурс.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #9 : Ноябрь 18, 2014, 23:54 »

Вы не правильно представляете работу условных переменных.
Смысл их в том, что вы лочите мутекс, проверяете доступность ресурса и если ресурс не доступен, то уходите на wait. Он разлочивает мутекс (для того чтобы другие нити могли его заполнить/сделать доступным) и усыпляет нить.
Когда происходит побудка, то нить просыпается в wait, который лочит мутекс и завершается. Мы может при залоченном мутексе опять проверить ресурс на доступность.

На форуме не раз поднималась тепа по услоаным переменным, в которых детально все говорилось.

Судя по этому описанию, я как раз всё понимаю правильно. И защищаемый ресурс есть, конечно же. Нет же никакого смысла в синхронизации потоков, если им не надо получать доступ к одному и тому же ресурсу, но ни в коем случае не одновременно. Просто если бы wait(&mutex) возвращал false при разлоченном мутексе, это было бы удобной информацией о доступности ресурса, значит его можно захватить (сделать mutex.lock()) и обрабатывать. А если ресурс недоступен, то сразу автоматом wait() становился бы в ожидание, и захватывал бы ресурс, как только тот освободится. Без этого приходится заводить, устанавливать, сбрасывать и проверять свой собственный флаг доступности ресурса, поскольку другого способа проверить это не существует. То есть, можно было бы удобнее инструмент иметь, но увы...
Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #10 : Ноябрь 19, 2014, 00:05 »

Перед тем как заснуть на wait, мы должны проверить, а есть ли для нас данные для обработки или нет.
Для этого мы лочим мутекс и лезем в наш ресурс (он то общий). Если данные есть, то при все еще запертом мутексе мы их достаем, разлочиваем мутекс и начинаем их обрабатывать. А вот если данных нет, то мы уходим на wait (мутекс все еще заперт) и уже он его разлочит.
Не очень понятно, для чего его освобождать перед wait и все это проверять + лочить руками?
Использовать мутекс в качестве флага плохая идея, тогда уж лучше взять семафор.
« Последнее редактирование: Ноябрь 19, 2014, 08:16 от Old » Записан
vulko
Гость
« Ответ #11 : Ноябрь 19, 2014, 09:04 »

Например контроль работы потока. Приостановить и продолжить работу.
Не очень понятно, что это за контроль? Для чего он нужен?
И я бы все равно сделал переменную bool pause, защитил ее мутексом и использовал ее для организации приостановки - это и был бы защищаемый ресурс.

Ессессно с bool pause. В соседнем топике уже приводил такой код.
Контроль простой. Есть поток с while(running) { }. Нужно его приостановить и продолжить работу. Например поток шлет данные. Либо поток хэндлить входящие данные. Много ситуаций.
Иногда он не нужен, но зачем его прибивать, если можно просто поставить в wait на время и не инициализировать заново.

Код:
void MyThread::run() {
    // init
    mContinue = new QMutex;
    mWaitCondition = new QWaitCondition;

    while(running) {
        lock();
        // do stuff
        unlock();

        if (pause) {
            mWaitCondition->wait(mContinue);
        }

        exec();
    }
}

void MyThread::pause() { pause = true; }

void MyThread::resume() {
    if (pause) {
        pause = false;
        mWaitCondition->wakeAll();
    }
}
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #12 : Ноябрь 19, 2014, 09:11 »

Вот для доступа к pause и нужен мутекс, и именно его нужно использовать в wait.
А почему он будет залочен при его передаче в wait я описал в предыдущем посте.
Записан
vulko
Гость
« Ответ #13 : Ноябрь 19, 2014, 09:16 »

Вот для доступа к pause и нужен мутекс, и именно его нужно использовать в wait.
А почему он будет залочен при его передаче в wait я описал в предыдущем посте.

Если много потоков могут делать pause/wake, то конечно нужен.
А если один, то мьютекс передаваемый в wait() может никем никогда не использоваться.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #14 : Ноябрь 19, 2014, 09:23 »

Если много потоков могут делать pause/wake, то конечно нужен.
А если один, то мьютекс передаваемый в wait() может никем никогда не использоваться.
Ну их как минимум два: один останавливающий, второй - останавливаемый.
И лучше сразу все делать правильно (никаких сложностей в этом нет), это сейчас поток один, а завтра их может быть уже 100500.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.089 секунд. Запросов: 23.