Russian Qt Forum

Qt => Общие вопросы => Тема начата: Гурман от Декабрь 08, 2014, 11:13



Название: Очистка и прочее управление очередями
Отправлено: Гурман от Декабрь 08, 2014, 11:13
Известно, что у Qt по необъяснимым причинам нет никакого управления очередями при соответствующих соединениях сигнал/слот. Очередь нельзя принудительно очистить, нельзя управлять её длиной, нельзя её "сливать" (игнорировать выход, если она никуда не подключена). Я искал объяснения, но ничего вменяемого не нашёл.

Есть желающие обсудить этот вопрос? Мне лично потребовалась необходимость очистки очереди и управления её длиной. Может стоит feature request написать? Или этот вопрос уже ранее поднимался (я с версии Qt 3.3 такого не помню, может прозевал)?


Название: Re: Очистка и прочее управление очередями
Отправлено: Пантер от Декабрь 08, 2014, 11:16
Для чего тебе понадобилась такая возможность? Скорее всего, можно проблему решить по-другому.


Название: Re: Очистка и прочее управление очередями
Отправлено: Гурман от Декабрь 08, 2014, 11:28
Для чего тебе понадобилась такая возможность? Скорее всего, можно проблему решить по-другому.

Для того, что в задаче нити общаются через очереди, а соединения между нитями могут динамически меняться, вплоть до отключения.  Надо иметь возможность очистки оторванной очереди и ограничения длины, чтобы нить при достижении очередью определенной длины останавливалась (как в случае QBlockingQueued). По-другому нормально - никак. А очереди в Qt - не объекты, во всяком случае, их структура снаружи не видна, их нельзя унаследовать и написать поверх них свой функционал.


Название: Re: Очистка и прочее управление очередями
Отправлено: Old от Декабрь 08, 2014, 11:46
Пришло время использовать свои очереди.


Название: Re: Очистка и прочее управление очередями
Отправлено: Пантер от Декабрь 08, 2014, 11:56
Да, свои очереди делай.


Название: Re: Очистка и прочее управление очередями
Отправлено: Igors от Декабрь 08, 2014, 12:38
Известно, что у Qt по необъяснимым причинам нет никакого управления очередями при соответствующих соединениях сигнал/слот. Очередь нельзя принудительно очистить, нельзя управлять её длиной, нельзя её "сливать" (игнорировать выход, если она никуда не подключена). Я искал объяснения, но ничего вменяемого не нашёл.
Это не совсем так. Есть метод compressEvent (правда не документированный)

Есть желающие обсудить этот вопрос? Мне лично потребовалась необходимость очистки очереди и управления её длиной. Может стоит feature request написать? Или этот вопрос уже ранее поднимался (я с версии Qt 3.3 такого не помню, может прозевал)?
Написание feature request - это как бы "жест доброй воли" или благотворительность. Возможно через годик Вы с удовольствием заметите "ага, молодцы, сделали!", но может и нет, им ведь тоже надо "поднимать проект". Во всяком случае надеяться решить свои проблемы с помощью feature request не стоит.

Я бы сначала поизучал compressEvent, сделал бы нужные операции с очередью как "тоже событие". Это просто предложение, оценивать типа "а вот это уже чепуха" не надо :)  Может и чепуха, может и нет.



Название: Re: Очистка и прочее управление очередями
Отправлено: Bepec от Декабрь 08, 2014, 13:09
Механизм сигнал слот в Qt отлажен и подходит под 99% нужд, не заставляя даже задумываться о том, как оно работает. А у вас задача как раз в 1% попадает, в котором вам надо изменить механизм.
И если допустим они возьмутся за реализацию управления всем этим, то придётся весь механизм переписывать. Сейчас он прост и не вызывает затруднений именно тем, что хрен кто в него влезет :D

PS моё мнение - проще вам свою очередь написать.


Название: Re: Очистка и прочее управление очередями
Отправлено: Гурман от Декабрь 08, 2014, 18:38
Свою очередь - однозначно не проще. Там всё по затылок в сигналах-слотах, а это означало бы написать их и большую часть приложения.

Причем 100% все нужные механизмы наверняка в очередях есть, иначе они бы вообще не работали. Просто наружу не вытащено.

Не вижу пока, как compressEvent может помочь хотя бы очистить очередь.


Название: Re: Очистка и прочее управление очередями
Отправлено: Bepec от Декабрь 08, 2014, 18:50
Всё там есть, и очистка, и получение количества сигналов, и многое другое. Вот ток оно внутри. Коммерческую лицензию и флаг в руки.


Название: Re: Очистка и прочее управление очередями
Отправлено: Igors от Декабрь 08, 2014, 19:09
Не вижу пока, как compressEvent может помочь хотя бы очистить очередь.
Да хотя бы так
Код
C++ (Qt)
bool MyApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
{
   if (event->type() == myClearAll) {
     postedEvents->clear();
     return true;
   }
   return QGuiApplication::compressEvent(event, receiver, postedEvents);
}
Только вряд ли это нужно/разумно делать

Свою очередь - однозначно не проще. Там всё по затылок в сигналах-слотах, а это означало бы написать их и большую часть приложения.
Категоричные суждения обычно поверхностны. Своя очередь практически неизбежна. Обычно она имеет высший приоритет (т.е. сначала выбираются все события из "своей" очереди, напр в eventFilter). Смешивать очереди не резон. Засылать события в свою очередь можно хоть напрямую, хоть с подскоком из того же compressEvent

Всё там есть, и очистка, и получение количества сигналов, и многое другое. Вот ток оно внутри. Коммерческую лицензию и флаг в руки.
Ну вот после таких ответов нервный ТС блокирует тему  :)
Цитировать
Суп на пароходе - прямо из Парижв! Открываешь кастрюльку - а там паааар..
:)


Название: Re: Очистка и прочее управление очередями
Отправлено: Гурман от Декабрь 08, 2014, 19:24
Увы, свою очередь делать не с руки, придётся весь механизм сигнал-слотов дублировать, потому что на него эта часть приложения полностью опирается. Общение между параллельными нитями сделано на сигналах и слотах, нити в плагинах, связывание сигналов и слотов автоматическое при загрузке плагинов, всё спроектировано, и в основном отлажено. А перепахивать приложение сейчас уже нет времени. На коммерческую лицензию сейчас денег никто не даст. А значит самый простой вариант - feature request, авось исполнится.


Название: Re: Очистка и прочее управление очередями
Отправлено: Old от Декабрь 08, 2014, 19:28
А значит самый простой вариант - feature request, авось исполнится.
Еще можно свечу в церкви поставить, может помочь. ;)


Название: Re: Очистка и прочее управление очередями
Отправлено: Igors от Декабрь 08, 2014, 20:07
Увы, свою очередь делать не с руки, придётся весь механизм сигнал-слотов дублировать, потому что ..
Чего это дублировать? Очереди "рабочих ниток" - что в них может быть кроме сигналов посланных из др ниток? По-моему аж ничего. Значит с ними можно напрямую. С главной ниткой так вряд ли прокатит, ну так если Вы собрались сливать/удалять - значит знаете что, т.е. интересующие события/получатели известны. Что мешает их выделить их отдельно? Выполнять их первыми - не проблема


Название: Re: Очистка и прочее управление очередями
Отправлено: Гурман от Декабрь 08, 2014, 20:22
Очереди "рабочих ниток" - что в них может быть кроме сигналов посланных из др ниток? По-моему аж ничего.

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


Название: Re: Очистка и прочее управление очередями
Отправлено: Гурман от Декабрь 08, 2014, 20:27
Не, писать свои очереди я пока не буду. А вот запрос на фичу уже написал.  ;D

Кстати, вспомнил - где-то еще в версии Qt 2.х, когда я с ним только знакомился, в его тусовке горячо обсуждался вопрос управления очередями. Противники говорили, что это нарушает принцип объектности и идеологию Qt, якобы дает возможность вмешательства в святыни. Сторонники говорили, что не будет нарушений, если очередью сможет управлять только тот, кто в неё посылает, этого будет достаточно. AFAIR тогда сказали, что это обсуждение будет продолжено в версии 3.х. Там, судя по всему, про это всё забыли. Но тогда еще не так горячо требовалась поддержка распараллеливания. Сейчас требуется. У меня в некоторые моменты времени работают 8 нитей одновременно, и это еще только середина разработки...


Название: Re: Очистка и прочее управление очередями
Отправлено: Bepec от Декабрь 09, 2014, 10:40
Ну я не сомневаюсь, что можно написать потоки с имитацией поддержки очереди сигналов :D
Получить все сигналы возможность есть. Получить все связи возможность есть.
Остаются простые вопросы как - при дисконнекте очередь теряется или остаётся.

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

PS придумали в общем какую то неживую архитектуру, где пользователь творит херню :D


Название: Re: Очистка и прочее управление очередями
Отправлено: Гурман от Декабрь 09, 2014, 11:35
Наибольшая проблема даже не при дисконекте - в этом случае в очередь сигналы перестают поступать, как выяснено. Проблема, когда соединение есть, а принимающая нить не запущена или по какой-то причине стоит в ожидании. Либо просто медленнее принимает, чем передающая передает. Вот тогда очередь начинает заполняться. И если даже остановить передатчик, то приемник получает всю труху, которая была послана. Избавиться от неё возможности нет.


Название: Re: Очистка и прочее управление очередями
Отправлено: Igors от Декабрь 09, 2014, 14:25
События (Events) я в своем приложении вообще не создаю и не использую, и не собираюсь - только обрабатываю всякие интерфейсные, которые сам Qt посылает, по необходимости.
Сигналы с QueuedConnection сами выливаются в Events.

Насчет "очистки", "объединения" очередей - это спорно/проблематично. Напр взял и очистил - а там сидел deleteLater. А потом еще найдется "исключение из правил" которое опять придется отслеживать. Как-то мутно получается.

Наибольшая проблема даже не при дисконекте - в этом случае в очередь сигналы перестают поступать, как выяснено. Проблема, когда соединение есть, а принимающая нить не запущена или по какой-то причине стоит в ожидании. Либо просто медленнее принимает, чем передающая передает. Вот тогда очередь начинает заполняться. И если даже остановить передатчик, то приемник получает всю труху, которая была послана. Избавиться от неё возможности нет.
Если используете wakeOne/All проверьте что мутекс захвачен, это коварная ошибка которая может долгое время не проявляться а тихо гадить.

По поводу Flush - да, такая нужда может возникнуть, но почему бы не решить это более простыми средствами? Напр установить нитке флаг "игнорировать события" а самому послать queued сигнал который этот флаг сбросит. При этом не нужно менять код обработчика, можно все сделать во внешнем фильтре.


Название: Re: Очистка и прочее управление очередями
Отправлено: Гурман от Декабрь 09, 2014, 15:25
Проблем с wakeOne/All у меня нет (вообще эти моменты на семафорах сделаны), остановка или просто задержка нити может происходить по внешним причинам. Например, передатчик быстро генерирует управляющие команды, а приёмник посылает их на внешний прибор и считывает с него ответ. А между посылкой команды и получением ответа надо выдерживать паузу 200 мсек. В результате приемник команд обрабатывает команды только каждые 0.2 сек. А передатчик команд может молотить их по чем зря. А потом прибор вдруг не ответил, выдал ошибку - приёмник команды должен выдать сообщение и стать в ожидании действия оператора. И после ответа оператора все команды, которые были посланы передатчиком, уже не нужны, их надо выкинуть - а они сейчас сидят в очереди. Это одна из возможных ситуаций, для которых надо специально предусматривать дополнительные синхронизации, сигналы управления, какие-то ухищрения и т.д. Хотя, если бы была просто приостановка передатчика по заполнению очереди некоей выделенной длины - это можно было бы использовать одинаково со всеми внешними приборами, которые имеют задержку ответа, и которые не имеют. Ну а без очистки очереди просто @$#%&@Q#... Пока пришлось в одном случае вые...ться и сделать специальный цикл выборки очереди в приемнике.

Насчет deleteLater - ИМХО это уже выдумка. Если такой объект послать в очередь обмена между нитями, то вообще не вполне понятно, когда он будет удален даже без очистки очереди. Может грохнуться в момент получения слотом в параллельной нити. Я бы такие объекты в очередь не пихал.


Название: Re: Очистка и прочее управление очередями
Отправлено: Igors от Декабрь 09, 2014, 16:19
Насчет deleteLater - ИМХО это уже выдумка. Если такой объект послать в очередь обмена между нитями, то вообще не вполне понятно, когда он будет удален даже без очистки очереди. Может грохнуться в момент получения слотом в параллельной нити. Я бы такие объекты в очередь не пихал.
Вы бы не пихали. А автор одного из Ваших плагинов - запихнул. Это я просто для примера, к тому что возможность "очистить очередь" вряд ли принесет много счастья, скорее наоборот, добавит головняка. Ведь придется разбираться что можно мочить а что нельзя - это как минимум несладко.

Ну а без очистки очереди просто @$#%&@Q#... Пока пришлось в одном случае вые...ться и сделать специальный цикл выборки очереди в приемнике.
Не вижу повода для эмоций/негодования. По-моему такое решение грамотнее и надежнее "очистки событий". Да, приемник оповещен и знает что до какого-то события надо игнорировать какие-то действия, что в этом плохого?



Название: Re: Очистка и прочее управление очередями
Отправлено: Гурман от Декабрь 09, 2014, 16:54
Насчет deleteLater - ИМХО это уже выдумка. Если такой объект послать в очередь обмена между нитями, то вообще не вполне понятно, когда он будет удален даже без очистки очереди. Может грохнуться в момент получения слотом в параллельной нити. Я бы такие объекты в очередь не пихал.
Вы бы не пихали. А автор одного из Ваших плагинов - запихнул. Это я просто для примера, к тому что возможность "очистить очередь" вряд ли принесет много счастья, скорее наоборот, добавит головняка. Ведь придется разбираться что можно мочить а что нельзя - это как минимум несладко.

Ну а без очистки очереди просто @$#%&@Q#... Пока пришлось в одном случае вые...ться и сделать специальный цикл выборки очереди в приемнике.
Не вижу повода для эмоций/негодования. По-моему такое решение грамотнее и надежнее "очистки событий". Да, приемник оповещен и знает что до какого-то события надо игнорировать какие-то действия, что в этом плохого?

Первый случай решается легко строкой в документации - "нельзя посылать в очередь объекты с deleteLater, кто послал, тот сам дурак". А вот второй случай означает, что авторам плагинов надо будет знать, в каких случаях писать собственный код для очистки очереди, в каких нет. Либо мне надо в родительском классе плагинов как-то предусматривать возможность выборки мусора из очереди (она может не в каждом случае потребоваться), чтобы самим авторам этого не пришлось делать, но тогда надо еще и в документации описать использование всего этого. То есть, отсутствие возможности просто очистить очередь одним вызовом, а вместо этого необходимость множества не совсем тривиальных действий, и порождает негодование. Тем более обоснованное, что внутри Qt это наверняка есть.


Название: Re: Очистка и прочее управление очередями
Отправлено: Igors от Декабрь 09, 2014, 17:35
Первый случай решается легко строкой в документации - "нельзя посылать в очередь объекты с deleteLater, кто послал, тот сам дурак". А вот второй случай означает, что авторам плагинов надо будет знать, в каких случаях писать собственный код для очистки очереди, в каких нет. Либо мне надо в родительском классе плагинов как-то предусматривать возможность выборки мусора из очереди (она может не в каждом случае потребоваться), чтобы самим авторам этого не пришлось делать, но тогда надо еще и в документации описать использование всего этого. То есть, отсутствие возможности просто очистить очередь одним вызовом, а вместо этого необходимость множества не совсем тривиальных действий, и порождает негодование. Тем более обоснованное, что внутри Qt это наверняка есть.
А не лучше ли не связываться ни с какой "очисткой" а решить это запросом статуса на приемнике и/или передатчике? Псевдокод как это решается в плагинах моей системы
Код
C++ (Qt)
SInt32 PluginCommand( UInt32 theCommand, .. )
{
switch (theCommand) {
 case commandCreateGeometry:
   for (size_t i = 0; i < N; ++i) {
     if (GetObjectStatus(dstObject) != noErr)
       return code_Aborted;
     AddVertex(dstObject, i, ...);
  }
  return noErr;
...
}
Т.е. перед посылкой запросить статус, а не так, "на деревню дедушке". Вообще всегда есть коды возврата и текущее состояние плагина - через них и надо действовать, т.е. цивильно, вместо цыганщины с "очисткой очереди".


Название: Re: Очистка и прочее управление очередями
Отправлено: Гурман от Декабрь 10, 2014, 01:07
Не поможет. Потому как когда в предыдущем примере приемник встанет по ошибке прибора, будет поздно пить боржоми - в очереди уже будет дофига ненужного. А если жестко синхронизировать передатчик и приёмник (напоминаю, что они в разных нитях), то они уже не независмы. Но по задаче подразумевается, что передатчик ничего не знает о приемнике, а приемник о передатчике. Приемники могут быть разные и передатчики разные. Даже обмен идет в QVariant обертках. И даже соединения могут меняться пользователем динамически.