Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: Igors от Декабрь 17, 2012, 22:30



Название: Использование QWaitCondition
Отправлено: Igors от Декабрь 17, 2012, 22:30
Добрый день

На мой взгляд, QWaitCondition - вещь хитрая, и надеяться на то что "прочитал ассистент и сделал по образцу" не приходится. Часто слышно "используй QWaitCondition", но доходит до дела - и никто не знает как :)  Ну так почему бы нам это не перетереть и не углУбить свои знания/понимание? Есть задачки на QWaitCondition - постите сюда, обсудим. Начнем с простого: вот пример неправильного использования. Я специально не привожу автора - все ошибаются, но дело не в том кто ошибся, а как правильно
Цитировать
т.е. строго по доке:

поток 1:

захват мутекса
wait
отпускаем мьютекс

поток 2:

wake
Ну насчет "строго по доке" - верить необязательно  :)

Да, и не надо спрашивать "а в чем вопрос?" - не каждый пост должен быть вопросом  :)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 17, 2012, 23:16
Кхм. Мини вопрос - а что там неправильного?

Возможно моих знаний не хватает. Возможно мой проект на неправильном использовании сделан и работает. Так в чём?


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 18, 2012, 10:27
Кхм. Мини вопрос - а что там неправильного?
Этот псевдокод не ведет к крашу и "при каком-то стечении обстоятельств" может быть работоспособным. Он просто наивен. Вызывая wakeOne/wakeAll из нитки 2 мы почему-то считаем, что нитка 1 ждет на QWaitCondition. Если это так - все норм. Однако если нитка 2 по каким-то причинам не успела встать на wait - все рушится. wake не имеет эффекта т.к. нет ожидающих на мутексе. И когда позже нитка 2 пришла на wait - ее уже некому разбудить.

Возможно мой проект на неправильном использовании сделан и работает.
Предъявляем псевдокод или упрощенный проект (Вам виднее) - посмотрим, пощупаем


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 18, 2012, 13:37
вырезанный код
Код:
/*
    private:
       QWaitCondition wait;
       bool flagStop;
       QMutex lock;
*/
public:

void run
{
    for(;!flagStop;)
    {
        lock.lock();
        wait.wait(&lock);

        if (turn.size() == 0)
        {
            lock.unlock();
            continue;
        }
        int tmpSize = turn.size();
        lock.unlock();
        for(;tmpSize != 0;)
        {
            createResultString(getTurn());
            tmpSize--;
         }
    }
}

void addTurn(некие данные inData)
{
    lock.lock();
    turn.push(inData);
    lock.unlock();
    wait.wakeAll();
}

Поток запущен, ждёт поступления данных.
Другие потоки читают/генерируют данные, вызывают функцию addTurn.
Поток просыпается, обрабатывает данные до конца очереди и опять засыпает.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 18, 2012, 14:14
вырезанный код
Код:
void run
{
    for(;!flagStop;)
    {
        lock.lock();
        wait.wait(&lock);

        for (;turn.size() != 0;)
        {
            // тут много много действий по обработке ;          
        }
    }
}
После выхода из wait.wait мутекс захвачен этой ниткой, поэтому уточните где Вы его освобождаете в run. Лучше исправьте/дополните Ваш пост, т.к. двоечтение и/или оговорку на словах обсуждать будет трудно


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 18, 2012, 15:32
Добавил в моё сообщение выше вырезку.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 18, 2012, 16:39
Ладно, давайте я распишу с комментариями
Код
C++ (Qt)
void run
{
   while (true) {
   {
      if (flagStop) break;   // проверяем флаг останова
      lock.lock();              // захватываем лок, др нитки не смогут изменить turn пока не освободим
      if (!turn.size())        // если в очереди нет задач -
        wait.wait(&lock);    // wait освободил мутекс, ждем побудки
 
// после возврата из wait мы опять владеем мутексом
// должны извлечь задачи из oчереди (turn) и освободить мутекс поскорее
// сколько задач извлекать - дело хозяйское
      int numExtract = turn.siize();
      if (mProcessMode == process_Single)  
         numExtract = qMin(numExtract, 1);
 
// извлекаем во временный контейнер  
      Container temp;
      for (int i = 0; i < numExtract; ++i)
        temp.push_back(turn.takeAt(0));
 
// освобождаем мутекс
       lock.unlock();
 
// обрабатываем извлеченные данные
      ProcessData(temp);
   }
}
 
Ваш код имеет 2 помарки

- не нужно делать wait если задачи в очереди есть, так некоторые задачи могут долго стоять в очереди если она не пополняется

- как только мутекс освобожден Вы не должны трогать turn до след захвата


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 18, 2012, 16:55
Эм?

1)
Если задачи в очереди есть? Это как? Этот код начинает выполняться в момент запуска потока.
Потому де факто у него нет данных. В дальнейшем wait будет ждать до тех пор, пока не появятся данные.
Когда появятся данные, все они будут обработаны, т.е. при следующей проходке цикла у нас опять получается отсутствие данных.

И если же сделать проверку, то я думаю, можно вполне попасть в ситуацию, когда 1 поток будет добавлять данные, а поток тут же их обрабатывать, не оставляя возможности другим потокам. (смутно, но думаю смысл донёс).

2)
Расписываю. Получаю мутекс, получаю размер полученных данных. Отпускаю мутекс.

Далее циклично вызывается слот createResultString(getTurn()).

getTurn() имеет в своем теле конструкция аля
Код:
    lock.lock();
    // получаем элемент из очереди. разблокируем. обрабатываем.     
    pars tmp;
    tmp = turn.front();
    turn.pop();
    lock.unlock();
    return tmp;
.

имеют ли ваши помарки обоснования, при этой добавочной информации?


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 18, 2012, 17:39
имеют ли ваши помарки обоснования, при этой добавочной информации?
Да, имеют, правда помарки не мои а Ваши :) Давайте по порядочку

1)
Если задачи в очереди есть? Это как? Этот код начинает выполняться в момент запуска потока.
Потому де факто у него нет данных. В дальнейшем wait будет ждать до тех пор, пока не появятся данные.
Когда появятся данные, все они будут обработаны, т.е. при следующей проходке цикла у нас опять получается отсутствие данных.
В жизни это происходит по-другому. Какое-то число wakeAll "съедается" т.к. нет ожидающих на мутексе. напр
Код:
        lock.unlock();
// В этот момент др нитка добавила новую задачу и сделала wakeAll которое  не имеет эффекта
        for(;tmpSize != 0;)
        {
Теперь представим себе что после этого задач (пока) не поступает. Тогда на след витке обработчик ждет на wait - хотя задача-то уже есть

Не спешите, здесь лучше разобраться капитально, вещь непростая


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 18, 2012, 17:56
И вправду слабое место тут есть, но к счастью не в моём проекте :D Имеется нитка, генерирующая постоянные события и данная технология используется для логгирования :)

А так да, вы правы. И каково же решение этой проблемы? Не отпускать мутекс, пока не будет обработано всё ? (или помещено в отдельный контейнер?) не будет ли это затратнее чем постоянно генерящиеся события?



Название: Re: Использование QWaitCondition
Отправлено: kuzulis от Декабрь 18, 2012, 18:18
Скорее всего не делать wakeAll :), а будить только те потоки, которые в этом нуждаются, не?

И вообще, какая используется "архитектура"? Один производитель и много потребителей?


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 18, 2012, 18:20
И каково же решение этой проблемы? Не отпускать мутекс, пока не будет обработано всё ?
Это плохо т.к. заставляет подающие нитки ждать конца обработки

(или помещено в отдельный контейнер?) не будет ли это затратнее чем постоянно генерящиеся события?
Реально очередь почти всегда - контейнер указателей на задачи, затраты на их перемещение пренебрежимо малы по сравнению с обработкой. В Qt может быть и не указатель, но с имплисит шарой тоже быстро. Вообще про временный контейнер я упомянул для полноты картины. Обработка "пачками" возможна, но встречается редко, действовать "по одному" проще, а тогда достаточно просто
Код
C++ (Qt)
temp = turn.takeAt(0);
lock.unlock();
ProcessData(temp);
 


Название: Re: Использование QWaitCondition
Отправлено: kuzulis от Декабрь 18, 2012, 18:28
Код
C++ (Qt)
temp = turn.takeAt(0);
lock.unlock();
ProcessData(temp);
 

А чем это в принципе отличается от:
Код
C++ (Qt)
// извлекаем во временный контейнер  
      Container temp;
      for (int i = 0; i < numExtract; ++i)
        temp.push_back(turn.takeAt(0));
 
// освобождаем мутекс
       lock.unlock();
 
// обрабатываем извлеченные данные
      ProcessData(temp);
 

?

В чем прикол то? Если for(i = 0...) тоже быстро выполнится, считаем, что затрат нет.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 18, 2012, 18:31
Скорее всего не делать wakeAll :), а будить только те потоки, которые в этом нуждаются, не?
Сильная  сторона WaitCondition как раз в том что будиться будут спящие, а уже работающим та побудка пофиг

И вообще, какая используется "архитектура"? Один производитель и много потребителей?
Та откуда я знаю? Учил транзисторы и даже лампы (1 семестр), яка там "архитектура"

В чем прикол то? Если for(i = 0...) тоже быстро выполнится, считаем, что затрат нет.
Нет никакого прикола - просто хочу по-одному, а могу и пачками (разные варианты, суть одна)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 18, 2012, 18:32
Много производителей и один потребитель :) Производители - потоки, генерящие данные. Потребитель - один этот поток, преобразующий в необходимую форму лог.

В моём случае несущественно.

to Igors:
Но ведь wakeAll тогда в любом случае может "пропустить" цикл. Как от этого избавиться?

PS в любом случае, я так понимаю, если в ожидающем цикле будут действия после unlock, это приведёт как раз к возможному пропуску wakeAll(). так ведь?

update:
В том то всё и дело, что в любом случае после unlock у нас получается участок времени (пусть пренебрежительно малый, но всё же), во время которого наш wakeAll умрёт и в очереди останется необработанная часть данных.

И даже несколько потоков не дадут 100% гарантии в покрытии этого места.


Название: Re: Использование QWaitCondition
Отправлено: kuzulis от Декабрь 18, 2012, 18:41
Кстати, помнится мне, что уже было на форуме аналогичное обсуждение (http://www.prog.org.ru/topic_21460_0.html).



Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 18, 2012, 18:51
to Igors:
Но ведь wakeAll тогда в любом случае может "пропустить" цикл. Как от этого избавиться?

PS в любом случае, я так понимаю, если в ожидающем цикле будут действия после unlock, это приведёт как раз к возможному пропуску wakeAll(). так ведь?

update:
В том то всё и дело, что в любом случае после unlock у нас получается участок времени (пусть пренебрежительно малый, но всё же), во время которого наш wakeAll умрёт и в очереди останется необработанная часть данных.

И даже несколько потоков не дадут 100% гарантии в покрытии этого места.
Ну что сказать - молодец, думает пацан, а не так себе, букварь всасывает (ой перехвалю  :))

Бояться пропуска wake не следует, в этом случае нас спасает счетчик данных. Если данные уже есть - извлекаем и обрабатываем, и только если нет - вызываем wait. Отсюда следует что WaitCondition ВСЕГДА используется со счетчиком, без него вся схема разваливается

Ладно, а слабо найти пробой в ассыстенте? (пример QWaitCondition)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 18, 2012, 20:50
Хвалить полезно, принимать хвалу опасно :)

Попробую разобраться завтра.

А так конечно да. Счётчик vs Wait на взгляд помогают решить эту проблему. Надо самому попробовать.


Название: Re: Использование QWaitCondition
Отправлено: Авварон от Декабрь 19, 2012, 12:22
Я конечно понимаю, что обсирать кутешную доку - любимое дело Igors'а, но, если бы кто-то удосужился в нее заглянуть, то сразу после некорректного примера написано
Цитировать
Also, if some of the threads are still in do_something() when the key is pressed, they won't be woken up (since they're not waiting on the condition variable) and so the task will not be performed for that key press. This issue can be solved using a counter and a QMutex to guard it.
После чего идёт пример со счётчиком (в него уже не вникал, ибо лень; но факт в том, что он есть).


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 19, 2012, 12:37
Я конечно понимаю, что обсирать кутешную доку - любимое дело Igors'а, но, если бы кто-то удосужился в нее заглянуть,
Аккуратнее пожалуйста, грубость и высокомерие Вас не украшают

После чего идёт пример со счётчиком (в него уже не вникал, ибо лень; но факт в том, что он есть).
О нем и речь


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 19, 2012, 12:50
Пожалуй меня в недоумение ввёл сон на 1 мс. Да и вызов wakeAll с залоченным мутексом.

А так - вроде нормально.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 19, 2012, 13:01
Пожалуй меня в недоумение ввёл сон на 1 мс. Да и вызов wakeAll с залоченным мутексом.

А так - вроде нормально.
Давайте для начала Вы приведете полный текст примера чтобы всем было однозначно ясно о чем речь. 


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 19, 2012, 13:23
Код:
// thread worker
     forever {
     mutex.lock();
     keyPressed.wait(&mutex);
     ++count;
     mutex.unlock();

     do_something();

     mutex.lock();
     --count;
     mutex.unlock();
 }

//control thread
     forever {
     getchar();

     mutex.lock();
     // Sleep until there are no busy worker threads
     while (count > 0) {
         mutex.unlock();
         sleep(1);
         mutex.lock();
     }
     keyPressed.wakeAll();
     mutex.unlock();
 }


Название: Re: Использование QWaitCondition
Отправлено: Авварон от Декабрь 19, 2012, 13:43
Аккуратнее пожалуйста, грубость и высокомерие Вас не украшают

Да нет, просто я регулярно (а точнее только их) вижу посты, содерщащие слова "писать по букварю", "обезьянки в ассистанте". Напрягает, если честно.

Тема хорошая и полезная (благодаря ей нашел у себя багу), однако постановка раздражает.


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 19, 2012, 13:44
По теме, господа, по теме.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 19, 2012, 14:34
Да нет, просто я регулярно (а точнее только их) вижу посты, содерщащие слова "писать по букварю", "обезьянки в ассистанте". Напрягает, если честно.
Насчет "обезьянок" - покажите где я такое допустил, извинюсь немедленно. Мне легко говорить - потому что не было такого :) "Букварь" - да, я говорю это часто, и что в этом плохого? Это базовая документация которую надо учить - в любой системе. Да, сначала надо "сделать по букварю" - может и проблем не возникнет.

На мой взгляд, беда в том что Qt букварь... слишком хорош, и это плохо (как бы "крайности сходятся"). Люди получают готовые, 100% разжеванные решения и.. моментально к этому привыкают. Какая там "удочка" если вокруг полным-полно вкуснейшей, жирнючей "рыбы" - хватило бы сил сожрать. Или не так?  :)

Тема хорошая и полезная (благодаря ей нашел у себя багу), однако постановка раздражает.
Ничего, переживете. А лучше подключайтесь-ка к изучению примера (см ниже) - там есть о чем поговорить, мне тоже далеко не все ясно/однозначно

----------

Верес, спасибо за copy/paste (ну просто здесь так надо). С чего начнем? Почему нужен sleep? Или где должен быть wake (внутри или снаружи захвата мутекса). Или где еще ошибка? Керуйте  :)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 19, 2012, 14:50
Зачем нужен слип в принципе понятно.
Непонятно зачем блочить мутекс каждый раз в while. И эти постоянные локи унлоки настораживают. (и помоему они подтормаживать должны?)

По видимому вполне возможна ситуация deadlock'a (или меня вводит в заблуждение отсутствие условия вызовов)
Код:
 while (count > 0) {
// тут     
         mutex.unlock();
         sleep(1);
         mutex.lock();
// тут
     }

Хотя если потумкать и если вызываются слоты в разных потоках, тогда код на вид нормальный.

Код:
// thread worker
     forever {
     mutex.lock();
     keyPressed.wait(&mutex);     //ждём wake
     ++count;
     mutex.unlock();

     do_something();

     mutex.lock();
     --count;
     mutex.unlock();
 }
                                             
//control thread
     forever {
     getchar();                          // а тут ждём нажатия чела для последующей итерации

     mutex.lock();
     // Sleep until there are no busy worker threads
                                             
     while (count > 0) {              //если есть работающие потоки, тогда даём им захватывать мутекс и закончить обработку.
         mutex.unlock();
         sleep(1);
         mutex.lock();
     }
                                             
     keyPressed.wakeAll();           // пробуждаем потоки все, они просыпаются и ждут освобождения мутекса (или крах если с одного потока)
     mutex.unlock();                   // а тут уже даём им старт
     }


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 19, 2012, 15:38
Зачем нужен слип в принципе понятно.
Непонятно зачем блочить мутекс каждый раз в while. И эти постоянные локи унлоки настораживают. (и помоему они подтормаживать должны?)

По видимому вполне возможна ситуация deadlock'a (или меня вводит в заблуждение отсутствие условия вызовов)
Код:
 while (count > 0) {
// тут     
         mutex.unlock();
         sleep(1);
         mutex.lock();
// тут
     }
Подтормаживать еще как должны - а что делать? Ведь здесь очереди-то нет (контейнера), приходится ждать пока обработчик "просрется" (навеяно предыдущим докладчиком). А просто так сделать sleep не катит - ведь мутекс захвачен нами, и обработчик не сработает до тех пор пока не освободим. Приходится сначала освобождать, ждать, потом опять захватывать. Вообще ихний пример как бы "наоборот" - показывает не силу а слабость примитива WaitCondition (ну вот, меня опять обвинят в нелояльности). Но базовый примитив на то и базовый - работать должно. Deadlock - откуда? Я захватил мутекс, я и освобождаю, никаких условий не использую 

Хотя если потумкать и если вызываются слоты в разных потоках, тогда код на вид нормальный.
"One thing at a time" как говорят буржуины. Или, по-нашему, "не гоните лошадей". Вот если все ясно почему sleep - тогда поехали дальше.


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 19, 2012, 15:55
Деадлок будет, если управляющий и работающий потоки окажутся в одной нити.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 20, 2012, 09:03
Ладно, пошли дальше.
Код:
// thread worker
     forever {
     mutex.lock();
     keyPressed.wait(&mutex);     //ждём wake
     ++count;
...
Да, счетчик вроде есть, но он используется уже после wait. Это не может работать правильно, в какой-то момент цикл обработки будет пропущен. Укажите как это происходит - или докажите что такое невозможно (и я не прав)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 20, 2012, 12:04
На мой взгляд всё нормально. счётчик увеличивается и уменьшается после wait. Т.е. если поток получил задачу и начал её выполнение он прибавляет счётчик. Как выполнит - уменьшает.

Выйти в  == 0 воркеры не могут. ибо в любой момент обработки count будет > 0.

Хотя если возникнет непредвиденное, может полететь всё.

PS и где пропуск?


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 20, 2012, 12:29
Выйти в  == 0 воркеры не могут. ибо в любой момент обработки count будет > 0.
Не в любой момент кода воркера
PS и где пропуск?
Ищите, ошибка та же самая - полагается что каждый wake будит


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 20, 2012, 13:17
В упор не вижу.

Там предполагается, что все потоки окончили обработку и застряли на wait.
Если потоки не окончили обработку, count будет > 0. Значит пробуждения не будет до окончания обработки. Нет?

 


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 20, 2012, 16:20
В упор не вижу.
Здесь надо чуть по-другому смотреть. Берете какое-то место в коде и говорите себе типа "пусть нитка заснула здесь" (ну забрал к нее ОС управление). Потом говорите "а в это время в замке..". Т.е. чем заняты др нитки? Как они могут нагадить? (обычно могут).

Если не дотумкаете - завтра скажу правильный (на мой взгляд) ответ.


Название: Re: Использование QWaitCondition
Отправлено: Авварон от Декабрь 20, 2012, 19:04
Ну есть ошибка если пользователь успеет нажать кнопочку и вейкнуть, пока рабочий тред будет проходить между последним анлоком и первым локом.


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 20, 2012, 20:46
Пользователь не может нажать кнопку, ибо в этот момент проходит цикл while  до последнего занятого потока. От этого и защищает счётчик.


Название: Re: Использование QWaitCondition
Отправлено: Авварон от Декабрь 20, 2012, 21:32
Еще раз - счетчик в 0. Рабочий поток стоит ПЕРЕД первым локом (ну не дали ему ни кванта времени). Юзер жмет кнопку. Цикл while скипается (никто еще даже не начинал работать) потоки вейкаются (а еще никто и не ждёт), и только после этого рабочий тред локает мьютекс и встает на вейт.
Ситуация маловероятна, но возможна.


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 20, 2012, 21:59
Код:
mutex.lock();
     keyPressed.wait(&mutex);
// вот тут поток ждёт.
// Как только происходит wake, mutex захватывается.
     ++count;
// count инкрементируется
     mutex.unlock();
// анлок для действий

Как он может пробудиться без захвата мутекса? Никак.


Название: Re: Использование QWaitCondition
Отправлено: Авварон от Декабрь 20, 2012, 22:07
3й раз - рабочий поток ВООБЩЕ ничего не успел сделать. Никто ничего не локал еще.

Код:
// thread worker
     forever { // мы вот тут стоим
     mutex.lock();
     keyPressed.wait(&mutex);
     ++count;


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 21, 2012, 07:00
Пока count не будет равным 0, контролирующий поток не даст пользователю щелкнуть кнопку.

Цитировать
3й раз - рабочий поток ВООБЩЕ ничего не успел сделать. Никто ничего не локал еще.

Это как? Как может быть такая ситуация? Поток ничего не успел сделать? А мб он ещё и не создан?

Думаю это притянуто за уши к пяткам. Ибо это уже вопрос проектирования. Потоки воркеры должны быть созданы и запущены раньше контрольного. Так же они уже все после запуска будут в wait. После чего начинается цикл аля кто быстрее, и не зря же им даётся целая мс на их работу.

PS можно и по указателю обратиться перед его инициацией. Такая же ошибка будет, помоему.


Название: Re: Использование QWaitCondition
Отправлено: GreatSnake от Декабрь 21, 2012, 07:45
и не зря же им даётся целая мс на их работу.
Вообще-то целая секунда)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 21, 2012, 07:48
Ох ты ж. Спутал с Sleep.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 21, 2012, 11:56
пока рабочий тред будет проходить между последним анлоком и первым локом.
Ну вот, это др дело. Можете (если хотите). Только с чего Вы взяли что это "только в первый раз"? Forever крутит любое число раз, и этот участок кода выполняется каждый раз  И насчет "маловероятно" Вы загнули, это еще как вероятно. Разжуем подробно

Код
C++ (Qt)
// thread worker
    forever {
// <--- нитка сейчас здесь
    mutex.lock();
    keyPressed.wait(&mutex);
    ++count;
    mutex.unlock();
 
    do_something();
 
    mutex.lock();
    --count;
    mutex.unlock();
}
 
Перед первым (в коде) локом мутекс свободен, и count == 0. Теперь смотрим что с др ниткой

Код
C++ (Qt)
//control thread
    forever {
    getchar();
 
    mutex.lock();
    // Sleep until there are no busy worker threads
    while (count > 0) {
        mutex.unlock();
        sleep(1);
<--- а эта нитка сейчас здесь
        mutex.lock();
    }
    keyPressed.wakeAll();
    mutex.unlock();
}
 
Она просыпается, захватывает лок, выходит из while (ведь count == 0), и (веселая, счастливая) вызывает wakeAll (кстати тоже неправильно, но об этом позже). Но на мутексе никто не ждет. Итог - "производитель произвел", а вот "потребитель" - ничего не "потребил". Более того, если производитель шустрый - он может напроизводить много чего - и все будет утеряно.

Думаю это притянуто за уши к пяткам. Ибо это уже вопрос проектирования. Потоки воркеры должны быть созданы и запущены раньше контрольного. Так же они уже все после запуска будут в wait.
Такого рода проектирование должно быть признано неполноценным и не заслуживающим обсуждения. Делая какие-то предположения о скорости выполнения Вы тем самым расписываетесь в том что сделать "просто корректно/нормально" Вы не можете. Зачем оно Вам надо? Ведь сделать правильно проще и лучше

А остальное - критикуем, опровергаем   :)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 21, 2012, 12:18
Помоему тут некая другая ситуация.

На мой взгляд имеется как раз модель нормального поведения - если поток готов работать, он сработает. Если нет - он не будет задействован (мало ли что с ним).

И мне кажется, что данный пример демонстрирует не "по нажатию кнопки работа N потоков", а "по нажатия кнопки работа свободных/готовых к обработке потоков".

PS во всяком случае упоминания о том, что этот пример будет всегда вызывать N потоков я нигде не видел.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 21, 2012, 12:46
Помоему тут некая другая ситуация.
Типичный малосодержательный пост по принципу "думать лень, напишу-ка что-нибудь, авось сойдет"  :)
Разговор о том что даже если всего 2 нитки (производитель и потребитель), запущенные в каком угодно порядке и уже отработавшие любое время - все равно "пакеты теряются", потреблено меньше чем произведено.


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 21, 2012, 14:05
Не надо называть мои посты малосодержательными. Я обижаюсь.

Затестил 2000 запусков управляющего потока. Проанализировал файл логов. Результат:
Код:
count  7988   error  0   tmpA  () 
Всего 7988 вызово из воркеров. 0 ошибочных (т.е. в каждых 4 выводах присутствовали только уникальные идентификаторы от 0 до 4). 3 вызова было пропущено всеми потоками (хз как откомментировать :D). А в общем нареканий особых нет.



Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 21, 2012, 14:32
Затестил 2000 запусков управляющего потока. Проанализировал файл логов. Результат:
Как говорили классики
Цитировать
Тестирование может показать наличие ошибок но не их отсутствие
Тем более что в данном случае тестирование затруднительно. Можно действовать гораздо проще.
Код:
     mutex.lock();
     keyPressed.wait(&mutex);
Увидев такой код Вы можете смело заявлять что это НЕВЕРНО. Потому что, как обсуждали выше, невозможно обеспечить пробуждение на каждый wake. Поэтому надо сначала проверить счетчик, и только если он нулевой - делать wait. Найти "где пробой" конечно интересно (хотя и "выносит моск") - но это совершенно необязательно. Всегда найдется такое хитросплетение ниток когда wake не имеет эффекта.

Так, ну и чего ждем? Изменяем пример чтобы было правильно  :)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 21, 2012, 14:45
А в любом случае где нибудь пробой да произойдёт, насколько я понимаю.
Идеальный в вашем понимании код как должен выглядеть?

Wait с счётчиком больше 0? А смысл?
Ведь инкремент идёт после пробуждения. До него wait будет бесконечным.

Смысл то в том, что счётчик сигнализирует управляющему, что рабочие заняты.

Чуть поясню для себя же.

Рабочий поток
Код:
//Создаём воркеры и управляющий
//count = 0;
//Проверяем счётчик
mutex.lock();
if (count > 0) // условие не выполнится никогда
    keyPressed.wait(&mutex);
//Что мы получаем? Ни один поток не начнёт никогда работать. Ибо в начале count = 0.

В данном примере count не является счётчиком необходимых для выполнения задач.
А является счётчиком работающих потоков.

PS я неправ?


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 21, 2012, 19:50
А в любом случае где нибудь пробой да произойдёт, насколько я понимаю.
Идеальный в вашем понимании код как должен выглядеть?

Wait с счётчиком больше 0? А смысл?
Ведь инкремент идёт после пробуждения. До него wait будет бесконечным.
Не хочу "размазывать цитаты", отвечу как бы пунктами

- верно, если нет опоры на счетчик, все равно пробьет

- схема WaitCondition одна и та же для потребителя (т.е. принимающего задачи). Называть ее идеальной нет смысла, другой просто нет. Я ее расписывал выше, просто повторяйте ее (конечно подставляя данные/переменные задачи). Возможно Вас сбило с толку что в первой редакции своего предыдущего поста я перепутал слова нулевой/ненулевой (ну зарапортовался, бывает :))

- "инкремент идет после пробуждения" - а почему это воспринимается как абсолютная истина? Только потому что так написано в букваре? Так возможны ошибки и там (пусть редко). Покажите творческий (а не механический) подход


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 21, 2012, 19:54
Кхм. Пошла уже демагогия по "абсолютную истину".

- Опора на счётчик не может быть в данном примере. Ибо он сделан с "необязательным" исполнением всех потоков.

- Угум. Приведите код схемы пожалуйста. Копать тему мне (да и другим) не особо хочется.

- Мы как бы разбирали пример. В данном примере инкремент в другом месте бессмысленен. Как бы выйти из этой ситуации?


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 21, 2012, 21:20
Кхм. Пошла уже ...
Ваш ответ поразительно напоминает другого молодого человека (ну Вы помните), опять-таки куча всяких причин, а 20 (максимум) строк кода - не дождетесь! Чего выкручиваться - ведь "шила в мешке не утаишь"  :)

Никогда не надо бояться сказать "да, сейчас я не могу этого сделать - ну не знаю как". Вот последние 2 недели я застрял с adaptive deep shadow sampling - да, ну не знаю как, ищу. Поиск решения - нормальное состояние программиста, остальное извращения.


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 22, 2012, 01:24
Эмм.. помоему тут как раз поговорка про бревно в своём глазу подойдёт :)

Вы предлагаете исправить данный пример, а кода от вас не дождёшься :D


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 22, 2012, 12:19
Вы предлагаете исправить данный пример, а кода от вас не дождёшься :D
Ага, "вот предложил - сам и исправляй" :) Ладно, подождем пару деньков, может найдутся смелые


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 22, 2012, 14:09
Я всё таки не вижу смысла в этом "исправлении". То, что вы предлагаете разительно отличается от текущего примера. То не исправление будет, а вообще другой подход и новый пример.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 24, 2012, 10:35
Причешем исходный пример
Код
C++ (Qt)
// thread worker
forever {
    mutex.lock();
    keyPressed.wait(&mutex);
    HandleTask();
    mutex.unlock();
}
 
Код
C++ (Qt)
//control thread
forever {
    getchar();
    mutex.lock();
    CreateTask();
    mutex.unlock();
    keyPressed.wakeAll();
}
 
Оба (HandleTask и CreateTask) могут быть сколь угодно сложными, могут освобождать мутекс и опять захватывать, использовать общие переменные (count) и.т.п. Но с точки зрения QWaitCondition нам совершенно не нужно вникать во все их подробности. Просто добавляем счетчик
Код
C++ (Qt)
// thread worker
forever {
    mutex.lock();
    if (!numTask)
      keyPressed.wait(&mutex);
    if (numTask) {
      --numTask;
      HandleTask();
    }
    mutex.unlock();
}
 
Код
C++ (Qt)
//control thread
forever {
    getchar();
    mutex.lock();
    CreateTask();
    ++numTask;
    mutex.unlock();
    keyPressed.wakeAll();
}
 
Нашего героя смутила переменная с именем "count", он подумал что это тот самый счетчик что и должен использоваться QWaitCondition. В действительности же "в огороде бузина, а в Киеве дядька"   :)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 24, 2012, 10:55
Кхм. У вас не "причёсанный" пример.

Вы вырезали проверку на наличие работающих потоков.
И в вашем случае работать будет только 1 поток.

Проще выражаясь вы убили многопоточность, у вас 1 производитель, 1 потребитель, и радуетесь этому?

Если непонятно, то в один момент времени у вас будет выполняться лишь 1 воркер. Многопоточность убита.


Подвожу краткую выжимку:

Что сделал Igors:
Удалил проверку на наличие работающих потоков.
Убил многопоточность.

Что получилось:
Получился один воркер и ненужный контрольный поток.
Ненужный потому, что с таким же успехом от него можно отказаться и функционал не изменится.

PS я вот одного не пойму, зачем вы убили многопоточность? Или я чего то не вижу и воркеры могут выполнять HandleTask параллельно?


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 24, 2012, 11:01
PS я вот одного не пойму, зачем вы убили многопоточность? Или я чего то не вижу и воркеры могут выполнять HandleTask параллельно?
Конечно могут. Никого я не убивал - просто перенес куски кода в ф-ции HandleTask и CreateTask, все работает как раньше - только теперь задачи не пропускает  :)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 24, 2012, 12:05
Код:
// thread worker
forever {
     mutex.lock();
     if (!numTask)
       keyPressed.wait(&mutex);
     if (numTask) {
       --numTask;
       HandleTask();// Вот тут выполняется задача.
     }
     mutex.unlock();
}

Как задача может выполняться параллельно, если мутекс может быть заблокирован только одним потоком????
У вас получается последовательное выполнение.

Код:
//worker 1
lock
функция
unlock
//worker 2
lock
функция
unlock
//worker 3
lock
функция
unlock

А нужно
Код:
lock-unlock // worker'ы прибавили счётчик, освободили мутекс.
//worker 1  worker 2   worker 3
функция    функция   функция
lock-unlock // worker'ы убавили счётчик, освободили мутекс.

В вашем примере нет многопоточного выполнения задачи. Есть простое последовательное выполнение. Мутекс ваш в воркере не даёт им параллельно выполнять задачу.

В примере же ассистента происходит параллельное выполнение ёмкой функции. Затраты на мутекс лок/анлок незначительны по сравнению с задачей.

Хотя нет, даже не так. Данный подход как раз и нужен для параллельного выполнения ресурсоёмких задач.

PS покажите мне параллельность в вашем примере. Как нубу/простачку покажите.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 24, 2012, 12:15
PS покажите мне параллельность в вашем примере.
Код
C++ (Qt)
void HandleTask( void )
{
   ++count;
    mutex.unlock();  // мутекс освобождается, др потребители могут работать (если для них есть задачи)
 
    do_something();  
 
    mutex.lock();
    --count;
}
 


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 24, 2012, 13:08
Вах, на виду то всё было, а я ж слепой да не заметил :)

И опять появляется некое count? Или у вас опечаточка с numTask?


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 24, 2012, 13:17
И опять появляется некое count? Или у вас опечаточка с numTask?
Он и не исчезал. Просто QWaitCondition нужен др счетчик, я его и добавил (numTask)


Название: Re: Использование QWaitCondition
Отправлено: Авварон от Декабрь 24, 2012, 14:25
Что-то я всё равно не понял. На просьбу показать параллельность Igors процитировал исходный пример кутешников.
А в его-то исправленном коде где анлок?


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 24, 2012, 14:28
Что-то я всё равно не понял. На просьбу показать параллельность Igors процитировал исходный пример кутешников.
А в его-то исправленном коде где анлок?
Так я же вызываю HandleTask. Никаких новых lock/unlock не было добавлено


Название: Re: Использование QWaitCondition
Отправлено: Авварон от Декабрь 24, 2012, 14:43
А, туплю.


Название: Re: Использование QWaitCondition
Отправлено: Old от Декабрь 24, 2012, 15:01
Код
C++ (Qt)
// thread worker
forever {
    mutex.lock();
    while (!numTask)
        keyPressed.wait(&mutex);
 
    --numTask;
    HandleTask();
    mutex.unlock();
}
 


Название: Re: Использование QWaitCondition
Отправлено: Old от Декабрь 24, 2012, 15:05
В Qt примере можно было запустить 5 воркеров и управляющий поток мог их параллельно запускать.
Сейчас не так.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 24, 2012, 15:10
Код
C++ (Qt)
// thread worker
forever {
    mutex.lock();
    while (!numTask)
        keyPressed.wait(&mutex);
 
    --numTask;
    HandleTask();
    mutex.unlock();
}
 
Согласен, так элегантнее
В Qt примере можно было запустить 5 воркеров и управляющий поток мог их параллельно запускать.
Сейчас не так.
Поясните почему


Название: Re: Использование QWaitCondition
Отправлено: Old от Декабрь 24, 2012, 15:17
Поясните почему

Код
C++ (Qt)
//control thread
forever {                                 // numTask = 0
    getchar();                          // Пользователь нажал кнопку
    mutex.lock();
    CreateTask();
    ++numTask;                        // numTask = 1
    mutex.unlock();
    keyPressed.wakeAll();           // Проснулись рабочие нитки, первая установит numTask = 0 и пойдет работать, а остальные рабочие нитки уснут на wait
}
 


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 24, 2012, 15:39
(не цитирую для экономии места). Да, мы создаем 1 задачу и будим только одну нитку, с этой точки зрения аккуратнее wakeOne. Но никто не мешает увеличить numTask на 2 или больше и тогда уже wakeAll. В любом случае сколько задач создать решает производитель. А в исходном примере некоторые рабочие нитки (потребители) могли остаться непробужденными, а задачи утерянными.


Название: Re: Использование QWaitCondition
Отправлено: Dancing_on_water от Декабрь 24, 2012, 15:51
Код:
Просто добавляем счетчик
// thread worker
forever {
     mutex.lock();
     if (!numTask)
       keyPressed.wait(&mutex);
     if (numTask) {
       --numTask;
       HandleTask();
     }
     mutex.unlock();
}
//control thread
forever {
     getchar();
     mutex.lock();
     CreateTask();
     ++numTask;
     mutex.unlock();
     keyPressed.wakeAll();
}

И сели в лужу, если потребителей больше создателей. Ситуация: создатель разбудил всех и ушел следующий чар ждать. numTask =1; Просыпается рабочий уменьшает счетчик numTask =0; За ним проспается второй рабочий, обнаруживает, что счетчик нулевой и уходит спать.


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 24, 2012, 16:51
Кстати последнее замечание верно :)

PS Igors добавь свою "очевидную" функцию в то сообщение. А то народ как и я умением видеть невидимое обделены :D


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 24, 2012, 17:16
И сели в лужу, если потребителей больше создателей. Ситуация: создатель разбудил всех и ушел следующий чар ждать. numTask =1; Просыпается рабочий уменьшает счетчик numTask =0; За ним проспается второй рабочий, обнаруживает, что счетчик нулевой и уходит спать.
Видимо в азарте меня уличить Вы не увидели мой предыдущий пост :) Да, именно так все и происходит, а чего будить 2 или более рабочих если работа есть только для одного? Дайте больше работ и будите больше работников. Заметим что для каких-то целей такая побудка все же годится (напр проснувшиеся могут проверить флажок abort)

PS Igors добавь свою "очевидную" функцию в то сообщение. А то народ как и я умением видеть невидимое обделены :D
Вижу - начинаете борзеть, значит пора дать следующую задачу :) Может лучше завтра создать новую тему, а то уже 5 листов, тяжеловато?  Или уже все ясно и больше не нужно?  :)


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Декабрь 24, 2012, 17:39
Не "борзеть", а указывать вам на ошибки. Ваша функция, которая нигде в том посте не описана вызывает стойкое желание прекращать разговоры. Ибо когда человек сначала говорит - всё ок, а через несколько часов добавляет - да всё просто, вот я просто не написал функцию - это немного. Невежливо.

И да, у вас опять же пример перекорёжен. Вместо побудки свободных потоков у вас опять таки идёт побудка какого то "определённого" количества.

Сможете сделать пример как в ассистенте, только без этого слабого места? Т.е. воркеры и управляющий. Управляющий будит рабочих только после полной их отработки?

PS А то получается как в сказке - обещал ему полцарства и коня, а дал палку с надписью полцарства и конь.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 24, 2012, 17:52
вызывает стойкое желание прекращать разговоры.
Хорошо, умолкаю  :)


Название: Re: Использование QWaitCondition
Отправлено: Dancing_on_water от Декабрь 24, 2012, 17:53
Видимо в азарте меня уличить Вы не увидели мой предыдущий пост :) Да, именно так все и происходит, а чего будить 2 или более рабочих если работа есть только для одного? Дайте больше работ и будите больше работников. Заметим что для каких-то целей такая побудка все же годится (напр проснувшиеся могут проверить флажок abort)
Когда, я начинал писать двух постов передо мной не было. Когда запостил, каюсь, не посмотрел. Но предложенный вами вариант решение проблемы с numTask - магическое число и это крайне плохое решение. Любой программист с опытом это подтвердит.

Однако это не все, вы говорите, что ошибка - пропуск задачи. Рассмотрим систему реального времени (каюсь, моя специлизация, поэтому беру примеры из этой области). Если потребитель зашел в wait позже, чем было выдано очередное задание, то это нештатная ситуация, т.к. при грамотном проектировании у него должен быть запас времени. Если этого запаса не хватило, это значит, что кто-то или что-то отжимает у него процессорные мощности. И если мы сейчас принудим его уйти на обработку мы рискуем сорвать временную диаграмму всей программы. В этом случае единственно верное решение - пропустить побудку и дать этому кому-то завершить свои дела. Такая ситуация и ее решение противоречит с вашим посылом.

Вообщем, я мог бы продолжить разговор о том, что вы еще не учли, но он мне не интересен. А читающим он будет бесполезен: все кто сейчас прочитал - те уже сами все выводы сделали, а уши тех, кто будут читать этот тред, что мозг откажиться переваривать много букв.

P.S. Ваши комплексы продолжают быть забавными. Старайтесь в том же духе.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 25, 2012, 10:18
Вместо побудки свободных потоков у вас опять таки идёт побудка какого то "определённого" количества.
Читаем первоисточник
Цитировать
For example, let's suppose that we have three tasks that should be performed whenever the user presses a key.
Как мы видим, речь идет о строго определенном, конкретном числе задач (3). Это нормальный, корректный подход к multithreaded, Мы не можем и не должны рассчитывать на то что какие-то нитки нас ждут, но мы железно гарантируем что все 3 будут (так или иначе) выполнены.

Управляющий будит рабочих только после полной их отработки?
Не врубаетесь в суть. Корректно "после того как все предыдущие задачи завершены". Это совсем не значит что нитка сделавшая задачу "отработала" и уже ждет на wait. Я умышленно выделил это место в ф-цию CreateTask которая может быть получена через copy/paste из исходного примера, но все-таки одну строчку нужно подправить.

Теперь такой момент. Автор может публиковать свое решение в том виде в котором считает нужным. Напр я считаю необходимым выделить HandleTask и CreateTask чтобы четко показать структуру алгоритма. Если Вас это не устраивает - это Ваши проблемы, но настойчивые требования все разжевать, положить в рот и помочь проглотить здесь неуместны.

Ладно, другой, более веселый разговор (из-за которого собственно я и вернулся в тему)
Но предложенный вами вариант решение проблемы с numTask - магическое число и это крайне плохое решение. Любой программист с опытом это подтвердит.
Зачем же прятаться за некоего "программиста с опытом"? :) Есть производитель(и), есть потребитель(и). Если производитель ничего не произвел - потребителю нечего потреблять. numTask - число произведенных товаров. Пусть магическое если хотите. Но как Вы представляете обойтись без него? Типа "пусть те потребители которые сейчас ничего не потребляют еще чего-то(?) потребят" - чушь собачья  :)

Далее Вы рассказываете о Вашей задаче в которой пропуск исходных данных допустим, и даже необходим. Это ассоциируются с теорией Эйнштейна, искривлением пр-ва и времени. А для нормального программиста утерянные данные - это просто баг за который можно получить и который надо исправлять. Поэтому если Вы хотели поговорить о чем-то особенном, изысканном, извращенном - место этому в отдельной теме.

А главное: если Вы хотите чего-то доказать - так ДЕЛАЙТЕ это. Предъявите Ваше решение, кратко поясните чем оно лучше другого (напр моего). И все всем станет ясно автоматычно. А так чем больше Вы стараетесь уверить окружающих в собственной крутизне - тем меньше верится.

Так что же все-таки мешает нашему танцору (кроме воды)?  :)


Название: Re: Использование QWaitCondition
Отправлено: Dancing_on_water от Декабрь 26, 2012, 09:36
Цитировать
А главное: если Вы хотите чего-то доказать
Изыди бес, нечистый своими помыслами! Покинь тело человека! До коли память короткая, то я тебе говорил, что здесь не ярмарка тщеславия. И я здесь появился не для того, чтобы что-то доказывать и красоваться. Также, если память коротка, обсуждение началось с выписанной мной из доки схемы. Так, если что-то и доказывал, так это ты.

Я же со своей стороны и по мере сил пытаюсь вразумить и направить тебя. Показать, что реальные задачи шире, и что твой подход только запутывают людей. Показать, что мастерство программиста заключается в умении там где надо решить задачу в общем виде, а там где надо применить частное решение.

Если продолжаешь упрямиться. То мой тебе совет: почитай по методы синхронизации про примитивы, про то как устроены потоки. Придумайте или найди в opensource себе задачу. Этот тред и твой пост - это все от недостатка опыта решения реальных, а не школьных задач.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Декабрь 26, 2012, 12:23
Изыди бес,
Типичный пост написанный в порыве горячности и неумения контролировать себя. Ничего, в следующий раз перед тем как бросаться словами подумаете что могут попросить за них ответить  :)


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 16, 2013, 10:59
Парни подмогните разобраться, начинаю разбираться с многопоточным программирование, это для меня в новинку.
Читаю уже 4й день Ваш пост и не могу воткнуть что и как, где пробои, в чем ошибки примеров, как баран на новые ворота.
Набросал код своего  Producer и Consumer.
Посмотрите есть ли ошибки или все правильно я понял и сделал свой пример.
Global var:
Код:
const int dataSize = 200;
const int bufSize = 10;
std::list<int> listTask;
std::list<QString> rezult;

QMutex mutexRezult;
QMutex mutex;
QWaitCondition bufNotFull;
QWaitCondition bufNotEmpty;

CProducer:
Код:
	void run()
{
for (int i = 0; i < dataSize; i++)
{
mutex.lock(); // Блокирем мютекс
while (listTask.size() == bufSize) // Если буфер полный
bufNotFull.wait(&mutex); // Ждем побудки буфер не полный

listTask.push_back(i); // Генерируем задачу

bufNotEmpty.wakeAll(); // Побудка что буфер не пустой
mutex.unlock(); // Разблокируем мютекс
}
}

CConsumer:
Код:
	void run()
{
for (int i = 0; i < dataSize; i++)
{
mutex.lock(); // Блокируем мютекс
while (listTask.size() == 0) // Если буфер пустой
bufNotEmpty.wait(&mutex); // Ждем побудки буфер не пустой

int task = *listTask.begin(); // Получаем задачу
listTask.pop_front();

bufNotFull.wakeAll(); // Побудка буфер не полный
mutex.unlock(); // Разблокируем мютекс

msleep(1 + rand()%100); // Обрабатываем задачу

// Выводим результат работы
QString s = tr("Thread = %1 *** Task = %2").
arg(m_numThread).
arg(task);
mutexRezult.lock();
rezult.push_back(s);
mutexRezult.unlock();
}
}
   

main:
   
Код:
	CConsumer consumer1(1);
CConsumer consumer2(2);
CConsumer consumer3(3);
CProducer producer;

consumer1.start();
   consumer2.start();
   consumer3.start();
producer.start();

Под конец кода у меня такой вопрос?
Нельзя ли заменять цикл:
while (listTask.size() == 0) на if(listTask.size() == 0)
и
while (listTask.size() == bufSize) на if (listTask.size() == bufSize)
и в чем разница.
            


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 16, 2013, 11:12
...или все правильно я понял...
Все правильно вы поняли.

Под конец кода у меня такой вопрос?
Нельзя ли заменять цикл:
while (listTask.size() == 0) на if(listTask.size() == 0)
и
while (listTask.size() == bufSize) на if (listTask.size() == bufSize)
и в чем разница.
Чем мешает цикл? :)
Смотрите, мы добавили одну задачу в очередь и будим все нити. Просыпается первая простаивающая и забирает это задание из очереди, просыпается вторая простаивающая, а задачи и нет. Тогда нить начнет выполнять тело цикла, т.е. заснет на wait опять.


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 16, 2013, 11:21
...или все правильно я понял...
Все правильно вы поняли.

Под конец кода у меня такой вопрос?
Нельзя ли заменять цикл:
while (listTask.size() == 0) на if(listTask.size() == 0)
и
while (listTask.size() == bufSize) на if (listTask.size() == bufSize)
и в чем разница.
Чем мешает цикл? :)
Смотрите, мы добавили одну задачу в очередь и будим все нити. Просыпается первая простаивающая и забирает это задание из очереди, просыпается вторая простаивающая, а задачи и нет. Тогда нить начнет выполнять тело цикла, т.е. заснет на wait опять.

1. Ага, ок
2. Т.е. while все таки нужен?
3. wakeAll - все потоки одновременно будятся? И выходит кто первый взял задачу тот и король, а все остальные в цикл опять попадают, потому что нет задач? Правильно?


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 16, 2013, 11:28
1. Ага, ок
2. Т.е. while все таки нужен?
3. wakeAll - все потоки одновременно будятся? И выходит кто первый взял задачу тот и король, а все остальные в цикл опять попадают, потому что нет задач? Правильно?
Да.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 16, 2013, 12:09
wakeAll - все потоки одновременно будятся? И выходит кто первый взял задачу тот и король, а все остальные в цикл опять попадают, потому что нет задач? Правильно?
Нет, будятся только те что ждут на WaitCondition, для других wake не имеет эффекта. Поэтому и нужен while. Поскольку Вы создаете 1 задачу, то аккуратнее wakeOne.


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 16, 2013, 12:42
Ок, спасибо, буду разбираться, если что отпишусь не судите строго.


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 16, 2013, 13:01
Нет, будятся только те что ждут на WaitCondition, для других wake не имеет эффекта. Поэтому и нужен while.
Еще разок можно прокомментировать этот момент?
Т.е. если поток прерван в другом месте, то WaitCodition его не разбудит это понятно.
А вот с while? Не могу воткнуть почему if нельзя сделать? Наверно if можно воткнуть если один поток генерит задачи, а другой обрабатывает а если несколько, то нельзя?
Воткните стрелочки где код остановлен в мой код для пояснинения, никак не могу уловить сути.



Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 16, 2013, 14:29
Т.е. если поток прерван в другом месте, то WaitCodition его не разбудит это понятно.
Прерван (вытеснен) или нет - неважно, если он не успел войти в ожидание то эффект поюудки нулевой

А вот с while? Не могу воткнуть почему if нельзя сделать? Наверно if можно воткнуть если один поток генерит задачи, а другой обрабатывает а если несколько, то нельзя?
Воткните стрелочки где код остановлен в мой код для пояснинения, никак не могу уловить сути.
Ну вот допустим
Код
C++ (Qt)
if (listTask.size() == bufSize) // Если буфер полный
bufNotFull.wait(&mutex); // Ждем побудки буфер не полный
 
Да, ушли на wait, да, проснулись по wake. Но ведь нет никаких гарантий что когда проснулись - в буфере есть место. Напр другой проснулся раньше и успел это место заполнить. Можно опять проверить if'ом но while лучше

Edit: смысл в том что wait освобождает мутекс до тех пор пока управление не вернется - а значит ситуация выходит из-под контроля


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 16, 2013, 15:45
Т.е. если поток прерван в другом месте, то WaitCodition его не разбудит это понятно.
Прерван (вытеснен) или нет - неважно, если он не успел войти в ожидание то эффект поюудки нулевой

А вот с while? Не могу воткнуть почему if нельзя сделать? Наверно if можно воткнуть если один поток генерит задачи, а другой обрабатывает а если несколько, то нельзя?
Воткните стрелочки где код остановлен в мой код для пояснинения, никак не могу уловить сути.
Ну вот допустим
Код
C++ (Qt)
if (listTask.size() == bufSize) // Если буфер полный
bufNotFull.wait(&mutex); // Ждем побудки буфер не полный
 
Да, ушли на wait, да, проснулись по wake. Но ведь нет никаких гарантий что когда проснулись - в буфере есть место. Напр другой проснулся раньше и успел это место заполнить. Можно опять проверить if'ом но while лучше

Edit: смысл в том что wait освобождает мутекс до тех пор пока управление не вернется - а значит ситуация выходит из-под контроля

Все, спасибо огромное, кажется начинаю втыкать!!!


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 16, 2013, 16:08
Нет
Да. Потому что это:
будятся только те что ждут на WaitCondition
и так очевидно. :)

А вот с while? Не могу воткнуть почему if нельзя сделать? Наверно if можно воткнуть если один поток генерит задачи, а другой обрабатывает а если несколько, то нельзя?
Смотрите, нить уснула на wait, когда ее будит wake, то управление получит она же, т.е. мы возвращаемся в wait.
При этом никто не гарантирует, что задания еще есть и их не выбрали более "быстрые" нитки. Значит, нам нужно после wait, еще раз удостовериться, что задания остались и если их нет, то снова заснуть на wait. Вот эта петля и решает эти действия.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 17, 2013, 09:44
Смотрите, нить уснула на wait, когда ее будит wake, то управление получит она же,
Это бесспорно, но вот тут есть одно подозрительное место
Код
C++ (Qt)
bufNotEmpty.wakeAll();
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 
а др нитка
Код
C++ (Qt)
bufNotEmpty.waitl(&mutex);
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 
А как мы знаем только одна нитка может владет мутексом. В каком же порядке они им овладевают? Или выходит что пробуждение случится только после того как будящий отдаст мутекс? И если будятся несколько, то понятно что порядок произволен, но может ли пробудившийся рассчитывать на то что остальные или еще спят, или уже отстрелялись и опять ждут на мутексе?


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 17, 2013, 10:29
Смотрите, нить уснула на wait, когда ее будит wake, то управление получит она же,
Это бесспорно, но вот тут есть одно подозрительное место
Код
C++ (Qt)
bufNotEmpty.wakeAll();
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 
а др нитка
Код
C++ (Qt)
bufNotEmpty.waitl(&mutex);
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 
А как мы знаем только одна нитка может владет мутексом. В каком же порядке они им овладевают? Или выходит что пробуждение случится только после того как будящий отдаст мутекс? И если будятся несколько, то понятно что порядок произволен, но может ли пробудившийся рассчитывать на то что остальные или еще спят, или уже отстрелялись и опять ждут на мутексе?
Я код реализации qwaitcondition_win.cpp посмотрел, мне кажется пробуждение случается на функции:
QWaitCondition::wakeAll()...SetEvent(current->event); - на ней, когда событие взводится.
???
А в чем слабость выше приведенного Вами кода?


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 17, 2013, 10:59
Это бесспорно, но вот тут есть одно подозрительное место
Код
C++ (Qt)
bufNotEmpty.wakeAll();
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 
а др нитка
Код
C++ (Qt)
bufNotEmpty.waitl(&mutex);
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 
А как мы знаем только одна нитка может владет мутексом. В каком же порядке они им овладевают? Или выходит что пробуждение случится только после того как будящий отдаст мутекс? И если будятся несколько, то понятно что порядок произволен, но может ли пробудившийся рассчитывать на то что остальные или еще спят, или уже отстрелялись и опять ждут на мутексе?

Не может такого быть!!! Докладываю как я вижу эту ситуацию!!!
Вот эта нитка точно владеет мьютексом:
Код
C++ (Qt)
bufNotEmpty.wakeAll();
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 

а другая нитка завладеет мьютексом, когда первая сделает и освободит мьтекс:
Код
C++ (Qt)
mutex.unlock();


потому что вторая его освободила точно:
Код
C++ (Qt)
bufNotEmpty.waitl(&mutex);

др. нитка:
Код
C++ (Qt)
bufNotEmpty.waitl(&mutex);
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 17, 2013, 11:16
Не может такого быть!!! Докладываю как я вижу эту ситуацию!!!
Вот эта нитка точно владеет мьютексом:
Хммм.... а почему "точно"? Напр wait освободит мутекс, потом опять захватит, почему здесь не так? А по-Вашему выходит что побудка как бы откладывается до тех пор пока будящий не осаободит мутекс. В это верится с трудом - он может заняться чем угодно и даже заснуть на др мутексе.

Что-то Old примолк (наверное изучает pthread_cond_signal)  :)


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 17, 2013, 11:27
Что-то Old примолк (наверное изучает pthread_cond_signal)  :)
А вы думаете я буду вам все разжевывать?
Этот вопрос отличная тема для самостоятельного изучения, вот разберитесь и доложите нам "как там что".
Кстати, на форуме это уже обсуждали и ответ есть в теме, в которой вы принимали бурное участие, только как всегда ничего из нее не вынесли.


Название: Re: Использование QWaitCondition
Отправлено: Bepec от Июль 17, 2013, 11:46
Некрофилы отакэ... Вроде бы забыли тему, ан нет, опять воду в ступе толкут :/


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 17, 2013, 12:44
А вы думаете я буду вам все разжевывать?
Этот вопрос отличная тема для самостоятельного изучения, вот разберитесь и доложите нам "как там что".
Кстати, на форуме это уже обсуждали и ответ есть в теме, в которой вы принимали бурное участие, только как всегда ничего из нее не вынесли.
"Разбирайся сам" - ответ на абсолютно любой вопрос. А значит и ценность такого ответа нулевая.

И почему Вы думаете что тот ответ верный? Он по существу повторяет последний пост Kosmonit, и, на мой взгляд, расходится со здравым смыслом. Да, и нехорошо пытаться задеть собеседника только потому что ответ Вам неизвестен  :)



Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 17, 2013, 12:51
"Разбирайся сам" - ответ на абсолютно любой вопрос. А значит и ценность такого ответа нулевая.
Ответ на вопрос ничего не дает, знания даются при самостоятельном изучении предмета. Поэтому, вы никогда не узнаете ответ на этот вопрос.

расходится со здравым смыслом.
"Ваш здравый смысл" часто расходиться со здравым смыслом. Форум уже не обращает на это внимание. :)

Да, и нехорошо пытаться задеть собеседника только потому что ответ Вам неизвестен  :)
Вот именно. Поэтому, перечитайте свой пост, на который я отвечал и скажите это себе. :)


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 17, 2013, 13:02
А по-Вашему выходит что побудка как бы откладывается до тех пор пока будящий не осаободит мутекс.
Я таки думаю что так, хренушки он опять захватит, пока мьютекс занят, а как освободит так и пробудится....


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 17, 2013, 13:04
Надо будет попробовать смоделировать эту ситуевину!


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 17, 2013, 13:27
Надо будет попробовать смоделировать эту ситуевину!
Отладочный вывод после каждой нужной строки и посмотреть на результат. ;)


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 17, 2013, 13:40
Ответ на вопрос ничего не дает,
Мне остается только игнорировать такой малосодержательный флуд ...

По существу - да, wake не имеет эффекта пока мутекс не освобожден - никто не проснется. Первый пробудившийся захватывает мутекс, остальные еще сидят в wait.  Когда этот первый освободит мутекс - следующий выйдет из wait и.т.д


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 17, 2013, 13:58
По существу wake это взвод флажочка. Ну это если совсем по существу. :)


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 17, 2013, 14:14
Хорошо, а вот такой квешн: все рекомендуют использовать wake при захваченном мутексе. Мотивировка типа: без захвата не запрещено, но смысла не имеет. Почему не имеет? Не понимаю куда смысл пропал?  :)


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 17, 2013, 14:16
Хорошо, а вот такой квешн: все рекомендуют использовать wake при захваченном мутексе. Мотивировка типа: без захвата не запрещено, но смысла не имеет. Почему не имеет? Не понимаю куда смысл пропал?  :)
Все это кто?


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 18, 2013, 08:26
Хорошо, а вот такой квешн: все рекомендуют использовать wake при захваченном мутексе. Мотивировка типа: без захвата не запрещено, но смысла не имеет. Почему не имеет? Не понимаю куда смысл пропал?  :)

Я таки думаю что бы не было такой ситуации, которую Вы описали:
Код:
bufNotEmpty.wakeAll();		
 <--- сейчас эта нитка владеет мутексом
mutex.unlock();
   
         
др. нитка:
Код:
bufNotEmpty.waitl(&mutex);		
 <--- сейчас эта нитка владеет мутексом
mutex.unlock();


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 18, 2013, 08:52
Я таки думаю что бы не было такой ситуации, которую Вы описали:
Такой ситуации не может быть в принципе.
wake просто устанавливает флажок, планировщик разбудит ждущую нитку, когда до нее дойдет очередь.
Нитка проснется в wait, который попытается сделать мьютексу lock, а если этот мьютекс будет занят кем-то другим, то нитка опять уснет, только на этом мьютексе и проснется, когда он освободится.


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 18, 2013, 08:53
Мотивировка типа: без захвата не запрещено, но смысла не имеет. Почему не имеет? Не понимаю куда смысл пропал?  :)
Понимаю, что "всех" вы сразу вспомнить не смогли. :)
Не слушайте "всех", читайте документацию. Там все четко написано, как нужно.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 18, 2013, 11:17
Ну вот я просто переставил 2 строчки
Код
C++ (Qt)
for (int i = 0; i < dataSize; i++)
{
mutex.lock(); // Блокирем мютекс
while (listTask.size() == bufSize) // Если буфер полный
bufNotFull.wait(&mutex); // Ждем побудки буфер не полный
 
listTask.push_back(i); // Генерируем задачу
 
// bufNotEmpty.wakeAll(); // Побудка что буфер не пустой
mutex.unlock(); // Разблокируем мютекс
bufNotEmpty.wakeAll(); // <----
}
Не вижу чем мне это грозит. Каким образом заклинит?


Название: Re: Использование QWaitCondition
Отправлено: Kosmonit от Июль 19, 2013, 12:40
Ну вот я просто переставил 2 строчки
Код
C++ (Qt)
for (int i = 0; i < dataSize; i++)
{
mutex.lock(); // Блокирем мютекс
while (listTask.size() == bufSize) // Если буфер полный
bufNotFull.wait(&mutex); // Ждем побудки буфер не полный
 
listTask.push_back(i); // Генерируем задачу
 
// bufNotEmpty.wakeAll(); // Побудка что буфер не пустой
mutex.unlock(); // Разблокируем мютекс
bufNotEmpty.wakeAll(); // <----
}
Не вижу чем мне это грозит. Каким образом заклинит?
Я думаю, что ничего не будет, но для перестраховки, я бы поместил разблокировку мьютекса после побудки...


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 19, 2013, 12:51
Я думаю, что ничего не будет, но для перестраховки, я бы поместил разблокировку мьютекса после побудки...
Я тоже, в конце концов когда-то надо "просто запомнить". Но привести пример когда рухнет если wait не под мутексом - я не могу. Примерчик сделал - работает, но это ничего не доказывает


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 19, 2013, 12:55
Я думаю, что ничего не будет, но для перестраховки, я бы поместил разблокировку мьютекса после побудки...
Зависит от реализации.
Вот для pthread четко прописано, будить при захваченом мьютексе. Возможно, где то будет подругому, хотя я сильно сомневаюсь.
Сейчас мы по сути пытаемся использовать разделяемый ресурс (условную переменную) без защиты мьютексом. Что может произойти, если две нитки полезут в wake, зависит от реализации этого самого wake.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 19, 2013, 13:06
Вот для pthread четко прописано, будить при захваченом мьютексе.
Не вижу этой четкости, напр
http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex (http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex)
Доказательство там очень неубедительное


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 19, 2013, 13:13
Аааааа. Вы бы еще ссылку на Хабр выложили. :)


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 19, 2013, 13:18
Аааааа. Вы бы еще ссылку на Хабр выложили. :)
По-моему stackoverflow - очень толковый сайт. Ну и никто не мешает Вам привести действительно авторитетный (по Вашему мнению) первоисточник, а еще лучше - сценарий краша "по ходам".


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 19, 2013, 14:46
По-моему stackoverflow - очень толковый сайт.
Почему вы тогда не верите написанному там? :)

Ну и никто не мешает Вам привести действительно авторитетный (по Вашему мнению) первоисточник.
man pthread_cond_signal

а еще лучше - сценарий краша "по ходам".
А еще лучше! (http://www.prog.org.ru/index.php?topic=23820.msg180658#msg180658)


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 19, 2013, 15:22
Почему вы тогда не верите написанному там? :)
Так а что ж там написано
Цитировать
Process B (incorrect):

condition = TRUE;
pthread_cond_signal(&cond);
То ясно что если я переменную condition меняю не под мутексом - отгребу. Но вот почему  pthread_cond_signal должен быть внутри - хз

А еще лучше! (http://www.prog.org.ru/index.php?topic=23820.msg180658#msg180658)
Ну и чего ото делать вид что это якобы очевидно? :) Не надо бояться сказать "не знаю", это часто проще и лучше


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 19, 2013, 15:26
Ну и чего ото делать вид что это якобы очевидно? :)
Для меня да. Вызов pthread_cond_signal(&cond); это доступ к разделяемому ресурсу без защиты мьютексом. Может быть все что угодно в зависимости от реализации.

Не надо бояться сказать "не знаю", это часто проще и лучше
Проще учиться думать и разбираться самому, а не спрашивать по форумам.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 19, 2013, 16:03
Проще учиться думать и разбираться самому, а не спрашивать по форумам.
А я и не просил Вас ни о какой помощи :) Просто интересно "почему". Хорошо, вот еще попытка доказательства
Цитировать
This is valid:

void *threadproc(void *data) {
    printf("Sending go signal\n");
    go = 1;
    pthread_cond_signal(&cond);
}

However, consider what's happening in main

while(!go) {
    /* Suppose a long delay happens here, during which the signal is sent */
    pthread_cond_wait(&cond, &lock);
}

If the delay described by that comment happens, pthread_cond_wait will be left waiting—possibly forever. This is why you want to signal with the mutex locked
Обратите внимание что вызов pthread_cond_signal не требует защиты (то же и в др источниках). Да, побудка будет упущена, в этом автор прав. Но как мы знаем, само по себе это не криминал. Если до того мы взвели go (под защитой) - то должно работать, задача не пропускается
Код
C++ (Qt)
pthread_mutex_lock(&lock);
go = 1;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
 
Или я ошибаюсь?


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 19, 2013, 16:13
Или я ошибаюсь?
Если несколько ниток будут писать и читать int без защиты мьютексом, будет работать?
Вроде будет, а потом... а на другой платформе... а на другой архитектуре...

Поэтому, мне совершенно не понятно, что доказывает (или не доказывает) этот пример.
Еще раз, я думаю, что разработчики pthread настаивают на вызове signal под защитой мьютекса, потому что в реализации самих функций работы с условной переменной (pthread_cond_xxx) могут быть "тонкие места", а не в пользовательском коде.


Название: Re: Использование QWaitCondition
Отправлено: Igors от Июль 19, 2013, 16:40
Если несколько ниток будут писать и читать int без защиты мьютексом, будет работать?
Как ни странно, в схеме WaitCondition - будет :) За счет второй переменной которая строго под мутексом.

Вроде будет, а потом... а на другой платформе... а на другой архитектуре...
Да конечно практичнее впихнуть под мутекс чем разбираться - я ж с этим не спорю. Но какой-то Вы совсем не любознательный, хотя еще молодой  :)


Название: Re: Использование QWaitCondition
Отправлено: Old от Июль 19, 2013, 16:46
Но какой-то Вы совсем не любознательный, хотя еще молодой  :)
А в чем здесь любознательность? Сейчас условные переменные реализовали так, завтра их реализуют по другому, под какой нибудь вендой по третьему? Мне нужно все изучить? Любознательный вы наш? :)

хотя еще молодой  :)
Нуу 40 лет это не возраст для мужчины.  ;D