LINUX.ORG.RU

План развития Qt


0

0

  • WebKit - слияние вебтехнологий и настольных приложений (поддержка в JS слотов/сигналов, расширение DOM дерева под эти 'настольные приложения')
  • Усиление поддержки XML (XML stream/потоки, XQuery/XPath)
  • IPC (разделяемая память, file mapping/проекция файлов в память, локальные сокеты, все это кроссплатформенное)
  • Улучшение базы для создания многонитевых приложений (собственно, какойто фреймворк замутить хотят под это дело)
  • Phonon в Qt (бекэнды: DirectX только под виндой :-) ИМХО, QuickTime и т.д)
  • Qt для Cocoa (64бит Mac на основе Cocoa API)
  • и т.д.
Вообще планов громадье, на данный момент их хватит до Qt 4.7.x. Взято из блога "aseigo" одного из основных разработчиков KDE. Сам "aseigo" ссылается по этой информации на Маттиаса Еттрича (Matthias Ettrich), Trolltech.
"Если Qt5 и случится, то не ранее 2011/2012. И в нем не будет таких болезненых изменений API, как в Qt4 по сравнению с Qt3."(aseigo)

>>> Подробности



Проверено: Shaman007 ()

Ответ на: комментарий от gaa

>Эта текучесть API в угоду удобству(зачастую, удобству написания >_простых_ программ) не делает большой чести проектировщикам WinAPI. >Ровно как и появляющиеся каждые 3 года новые версии .net framework, где >приходится долго портировать продукт. Вот юниксным форкам более >тридцати лет и никто их не депрекейтил :)

API вроде никуда не утекает . Иначе не будет обратной совместимости . Просто старые вызовы реализуются с помощью новых функций или в заголовичных файлах старий API через #define преобразуется в новый .

anonymous
()
Ответ на: комментарий от anonymous

> 1.Не Вы же поддерживаете системную библиотеку , какая Вам разница ? Вас же не сильно расстаивает что libc и ядро unix(linux) тоже не маленькие ?
Кстати, огромный libc меня расстраивает, особенно при апгрейде какого-то мелкого пакета, который ссылается на более новый libc через модем :)
А то, что компании-производителю будет сложнее отлавливать ошибки в библиотеке, меня волнует, т.к. любая моя программа подразумевает стабильность и безглючность используемых библиотек.

> 2.Я не понял как из первого предложения следует второе ? Если человек путает разные подходы к решению одной задачи , то это проблема опять же не разработчиков Win32.
Не следует, это два отдельных высказывания.
Как я уже говорил, разработчик из нежелания читать сотни статей MSDN использует тот метод, который ему больше приглянулся. И не факт, что самый лучший.

> 3.Ну что с таймерами не так ? Что там сложного ? Приведите пример .
Уже приводил, читайте выше.

> 4.Риск не ознакомиться с документацией есть всегда :-)
Когда документации меньше(например, десяток вызовов традиционного UNIX IPC vs несколько гигабайт MSDN), то больше вероятность её охватить и обдумать лучший путь сразу, а не когда разработка зайдёт в тупик.

> 5.Зачем сразу изучать все функции ? Вы решаете конкретную задачу , а не пишете энциклопелию
Затем, чтобы решить её более хорошо и красиво => ей будет легче отлаживать и поддерживать

gaa ★★
()
Ответ на: комментарий от klalafuda

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

А чем тут не подходит стандартная системная очередь сообщений?

gaa ★★
()
Ответ на: комментарий от anonymous

>>Эта текучесть API в угоду удобству(зачастую, удобству написания >>_простых_ программ) не делает большой чести проектировщикам WinAPI. >>Ровно как и появляющиеся каждые 3 года новые версии .net framework, где >>приходится долго портировать продукт. Вот юниксным форкам более >>тридцати лет и никто их не депрекейтил :)

> API вроде никуда не утекает . Иначе не будет обратной совместимости . Просто старые вызовы реализуются с помощью новых функций или в заголовичных файлах старий API через #define преобразуется в новый .

Я употребил слово "текучесть" в смысле "изменяемость".

gaa ★★
()
Ответ на: комментарий от gaa

> надеюсь, в дальнейшей дискуссии тема раскроется более полно, но Ваши слова заставят меня впредь быть с pthreads более осторожным

на эту и другие темы, связанные с потоками, если хорошая книга:

PThreads Primer
A Guide to Multithreaded Programming
Bil Lewis
Daniel J. Berg

http://ianzag.megasignal.com/tmp/Threads%20Primer%20-%20A%20Guide%20to%20Mult...

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от gaa

> А чем тут не подходит стандартная системная очередь сообщений?

а именно? какая стандартная очередь сообщений?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>> А чем тут не подходит стандартная системная очередь сообщений?

> а именно? какая стандартная очередь сообщений?

Которая message queue. msgget(), msgctl(), msgsnd(), msgrcv() и т.д.

gaa ★★
()
Ответ на: комментарий от gaa

> Которая message queue. msgget(), msgctl(), msgsnd(), msgrcv() и т.д.

а чем она вам поможет? AFAIU дескриптор очереди не работает с select(2) & K.

http://www.opengroup.org/onlinepubs/009695399/functions/select.html

--- cut---
The pselect() and select() functions shall support regular files, terminal and pseudo-terminal devices, [XSR] [Option Start] STREAMS-based files, [Option End] FIFOs, pipes, and sockets. The behavior of pselect() and select() on file descriptors that refer to other types of file is unspecified.
--- cut---

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>> Но я не понимаю, зачем это нужно: основная нить не принимает соединения, и больше ничем не знимается,

>ну почему же ничего не делает? вполне даже делает.

>штатный пример - основная нить занимается обработкой сигналов

То есть никаких "долгих" задач, которые нужно распараллеливать, она не выполняет.

>> а приняв его, отдает в очередь, на которой ожидают рабочие нити. Рабочая нить обрабатывает запрос до конца, больше не общаясь с основной.

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

Нет, не приходим. Очередь может быть единая для всех - это нормально, поскольку "писатель" у очереди всего один: главная нить.

> после перебора немногочисленных вариантов по всей очевидности придем к стандартной схеме "родительский socketpair() + select() в дочернем потоке"

Таки я не понял - почему именно она, а не очередь на condvar.

>> Единственное, зачем здесь прерывать исполнение рабочей нити - это завершение работы,

> не единственное. может быть внешнее требование об обновлении какой-то конфигурации сервиса etc etc.

И насколько часто это делается? Насколько быстрой должна быть реакция? Является ли обязательным корректная орбаботка изменения конфигурации в процессе обработки запроса? (последнее, ИМХО - задача, неразрешимая в общем случае). Чем не устраивает вариант "дождаться завершения всех запросов"?

> в приложении может быть достаточно сложная логика, которая подразумевает наличие нескольких пулов потоков etc etc etc

Ну вот, опять... можно озвучить весь список требований?

tailgunner ★★★★★
()
Ответ на: комментарий от klalafuda

>> А чем тут не подходит стандартная системная очередь сообщений?

> а именно? какая стандартная очередь сообщений?

Которая не SysV, а man mq_open

tailgunner ★★★★★
()
Ответ на: комментарий от klalafuda

>> Которая message queue. msgget(), msgctl(), msgsnd(), msgrcv() и т.д.

> а чем она вам поможет? AFAIU дескриптор очереди не работает с select(2) & K.

Ну не мне, а Вам в озвученной Вами задаче. Достаточно проверять очередь сообщений дочерним потоком после завершения каждого кванта работы, чтобы проверить, "не поступило ли чего".

gaa ★★
()
Ответ на: комментарий от gaa

>Как я уже говорил, разработчик из нежелания читать сотни статей MSDN >использует тот метод, который ему больше приглянулся. И не факт, что >самый лучший.

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

> 3.Ну что с таймерами не так ? Что там сложного ? Приведите пример . >Уже приводил, читайте выше.

Уже кажется выяснили , что использование таймеров в той ситуации ничем не оправдано . Только ленью или незнанием Win32 .

>Когда документации меньше(например, десяток вызовов традиционного >UNIX IPC vs несколько гигабайт MSDN), то больше вероятность её >охватить и обдумать лучший путь сразу, а не когда разработка зайдёт в >тупик.

Как можно сравнить десяток вызовов UNIX IPC с гигабайтами MSDN ? Тогда можно сравнить с терабайтами Google :-) Давайте сравнивать UNIX IPC с тем что описано в Platform SDK для работы с многопоточными программами.

> 5.Зачем сразу изучать все функции ? Вы решаете конкретную задачу , а >не пишете энциклопелию >Затем, чтобы решить её более хорошо и красиво => ей будет легче >отлаживать и поддерживать

Я не понял . То Вы жалуетесь что влом читать MSDN , то утверждаете что все-таки прочитать надо . MSDN - это справочник по всему что есть у Microsoft . Читайте только те разделы , которые касаются вашей задачи.

anonymous
()
Ответ на: комментарий от tailgunner

> То есть никаких "долгих" задач, которые нужно распараллеливать, она не выполняет.

остановимся на варианте, когда основной поток ничего не выполняет и спит на sigsuspend() в ожидании асинхронные сигналы к обработке.

> Нет, не приходим. Очередь может быть единая для всех - это нормально, поскольку "писатель" у очереди всего один: главная нить.

как вы себе представляете "одну очередь" на все потоки? интересуют технические подробности реализации. думаю, псевдокода вполне хватит.

> Таки я не понял - почему именно она, а не очередь на condvar.

потому, что API условных переменных не совместимо с API системных вызовов. они ортогональны.

пример:
у нас есть условная переменная C и есть поток T. посредством C мы желаем оповестить T о каком-то событии. в свою очередь, T желает прочитать данные из сокета по read()/recv() которые могут заблокироваться.

вопрос:
нарисуйте мне схему, в которой T будет с одной стороны ожидать данные из сокета а с другой ожидать события на C.

> И насколько часто это делается?

вопрос "часто" здесь не уместен. вполне достаточно утверждения, что а) это делается б) это делается один или более раз.

> Насколько быстрой должна быть реакция?

максимально короткой aka на столько быстрой, сколько позволяет система и ресурсы.

> Является ли обязательным корректная орбаботка изменения конфигурации в процессе обработки запроса? (последнее, ИМХО - задача, неразрешимая в общем случае).

к POSIX API как таковому это отношения не имеет. каким образом поток будет обрабатывать полученный запрос, что будет делать с ошибками etc etc - это уже совершенно другой уровень и как минимум зависит от конкретной задачи.

> Чем не устраивает вариант "дождаться завершения всех запросов"?

какое-то время поток тратит в ожидании поступления запроса к исполнению -> его вообще может никогда не поступить -> поток может просто спать в read()/accept()/etc причем произвольное время.

>> в приложении может быть достаточно сложная логика, которая подразумевает наличие нескольких пулов потоков etc etc etc

> Ну вот, опять... можно озвучить весь список требований?

требований к чему именно?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от anonymous

>>Как я уже говорил, разработчик из нежелания читать сотни статей MSDN использует тот метод, который ему больше приглянулся. И не факт, что самый лучший.

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

Не всегда есть время на осваивание большого(!) количества материала.

>>> 3.Ну что с таймерами не так ? Что там сложного ? Приведите пример .

>>Уже приводил, читайте выше.

> Уже кажется выяснили , что использование таймеров в той ситуации ничем не оправдано . Только ленью или незнанием Win32 .

Да.

>>Когда документации меньше(например, десяток вызовов традиционного UNIX IPC vs несколько гигабайт MSDN), то больше вероятность её охватить и обдумать лучший путь сразу, а не когда разработка зайдёт в тупик.

> Как можно сравнить десяток вызовов UNIX IPC с гигабайтами MSDN ? Тогда можно сравнить с терабайтами Google :-) Давайте сравнивать UNIX IPC с тем что описано в Platform SDK для работы с многопоточными программами.

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

Давайте читать platform sdk. Но быдлокодер Вася Пупкин, который, например, пишет незаменимую вещь типа 1C не станет разбираться, а сделает как ему проще. В unix ipc таких простых способов для ленивых нет, потому оно _прививает_ хороший стиль.

> Я не понял . То Вы жалуетесь что влом читать MSDN , то утверждаете что все-таки прочитать надо . MSDN - это справочник по всему что есть у Microsoft . Читайте только те разделы , которые касаются вашей задачи.

Читать надо толковое сжатое руководство. К этой категории я отношу man, qt assistant, но не отношу MSDN.

PS. а пробел перед знаками препинания в Ваших сообщениях - это борьба с глюками punto switcher или xneur?

gaa ★★
()
Ответ на: комментарий от klalafuda

> пример: у нас есть условная переменная C и есть поток T. посредством C мы желаем оповестить T о каком-то событии. в свою очередь, T желает прочитать данные из сокета по read()/recv() которые могут заблокироваться.

> вопрос: нарисуйте мне схему, в которой T будет с одной стороны ожидать данные из сокета а с другой ожидать события на C.

Это пример из серии плохой архитектуры. На месте T должно быть 2 потока: один отвечает за переменную и управление вторым потоком согласно её изменению, а второй - читает/пишет в сокет.

gaa ★★
()
Ответ на: комментарий от tailgunner

>> а именно? какая стандартная очередь сообщений?

> Которая не SysV, а man mq_open

вариант ни чуть не лучше. впрочем, если вы приведете пример кода, который бы показывал, как можно ожидать события на сокете и mq или, тем более, на условной переменной и mq, это будет повод для обсуждения.

http://www.opengroup.org/onlinepubs/009695399/functions/mq_open.html

--- cut ---
A message queue descriptor may be implemented using a file descriptor, in which case applications can open up to at least {OPEN_MAX} file and message queues.
--- cut ---

дескриптор очереди *может* быть реализован как (но не обязан!) файловый дескриптор и про то, что его можно передавать куда-то помимо вызовов mq_xxx ни слова.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от gaa

> Это пример из серии плохой архитектуры. На месте T должно быть 2 потока: один отвечает за переменную и управление вторым потоком согласно её изменению, а второй - читает/пишет в сокет.

отлично! отлично, сэр... давайте разобъём её на два потока, как вы и посоветовали:

поток A читает данные из сокета:

while (1) {
read();
}

поток B отвечает за условную переменную и отвечает за управление потоком A:
<вставьте ваш вариант кода для прерывания исполнения потока A>

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

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от gaa

>PS. а пробел перед знаками препинания в Ваших сообщениях - это борьба с >глюками punto switcher или xneur?

Есть анекдот про профессора которого спросили кладет ли он бороду на одеяло когда спит или под одеяло . Я в панике :-) Или я так пишу или это делает движок lor.

anonymous
()
Ответ на: комментарий от klalafuda

> как вы себе представляете "одну очередь" на все потоки?

В виде condvar и буфера, прикрытого мютексом.

> интересуют технические подробности реализации. думаю, псевдокода вполне хватит.

Дружище, какой псевдокод? condvar'ы предназначены именно для таких вещей. Чем не устраивает man pthread_cond_wait?

>> Чем не устраивает вариант "дождаться завершения всех запросов"?

> какое-то время поток тратит в ожидании поступления запроса к исполнению -> его вообще может никогда не поступить -> поток может просто спать в read()/accept()/etc причем произвольное время.

насчет accept - его выполняет главная нить, насчет read - цикл poll/read спасет.

>>> в приложении может быть достаточно сложная логика, которая подразумевает наличие нескольких пулов потоков etc etc etc

>> Ну вот, опять... можно озвучить весь список требований?

>требований к чему именно?

К приложению. В частности - чем сложная логика и несколько пулов могут помешать осуществит простую схему "главная нить только раздает дескрипторы".

tailgunner ★★★★★
()
Ответ на: комментарий от klalafuda

> поток B отвечает за условную переменную и отвечает за управление потоком A:

while (1) { pthread_cond_wait(variable); pthread_kill(other_thread); }

gaa ★★
()
Ответ на: комментарий от gaa

>Давайте читать platform sdk. Но быдлокодер Вася Пупкин, который, например, пишет незаменимую вещь типа 1C не станет разбираться, а сделает как ему проще. В unix ipc таких простых способов для ленивых нет, потому оно _прививает_ хороший стиль.

Кстати, кусок Win32 API который отвечает за файлы & сеть, Threading & Synchronization, IPC и пр. негуевые вещи очень даже хорош и документирован хорошо. В Platform SDK хреново описан только ГУЙ. Да и по функционалу он не сильно превосходит голый X11. MFC очень плох. WTL они релизят неподдерживаемым

Absurd ★★★
()
Ответ на: комментарий от klalafuda

> дескриптор очереди *может* быть реализован как (но не обязан!) файловый дескриптор

Знаю. Я посчитал, что речь уже зашла о Линукс - mq_open, прежде всего, не везде есть.

tailgunner ★★★★★
()
Ответ на: комментарий от gaa

>> поток B отвечает за условную переменную и отвечает за управление потоком A:

>while (1) { pthread_cond_wait(variable); pthread_kill(other_thread); }

Дружище, перестань позориться.

tailgunner ★★★★★
()
Ответ на: комментарий от gaa

> Расскажи, где я опозорился

SysV IPC ты упомянул ни к селу, ни к городу. SysV IPC вообще никогда нормально с Unix-примитивами не интегрировались.

condvar - гораздо более сложная вещь, чем тебе кажется.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> В виде condvar и буфера, прикрытого мютексом.
> Дружище, какой псевдокод? condvar'ы предназначены именно для таких вещей. Чем не устраивает man pthread_cond_wait?
> насчет accept - его выполняет главная нить, насчет read - цикл poll/read спасет.

итого, получаем схему:

1. основная нить выполняет accept()
по всей видимости, получив соединение, основная нить:
а) создает поток для его обработки или же
б) помещает соединение в некую очередь, из которой его подхватывает заранее созданный поток обработки.
выберем мы а или б в сущности не важно aka на ваш выбор.

2. рабочий поток, получив файловый дескриптор сокета, желает прочитать из него запрос. для этого он:
а) вызывает блокирующийся read() и ждет данных
б) переводит сокет в неблокирующийся режим и ждет данные через связку select()->read()
опять же не так важно, какой вариант мы выберем aka на ваш выбор.
3. в конце-концов, прочитав из сокета запрос, рабочий поток что-то с ним делает и пишет в сокет аналогичным образом ответ.
4. после обработки запросы возвращаемся к п.2

теперь, вопрос:
в какое место в дочернем потоке нам нужно вставить условную переменную так, чтобы поток мог на неё оперативно отреагировать? допустим для ясности, что она сигналится бродкастом из основного потока по какому-то произошедшему в нем событию.

вопрос вам понятен, или нужны уточнения?

> К приложению. В частности - чем сложная логика и несколько пулов могут помешать осуществит простую схему "главная нить только раздает дескрипторы".

давайте все-таки определимся с самым простым примером, который я привел выше. все остальное лишь следствие.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от tailgunner

>> Расскажи, где я опозорился

> SysV IPC ты упомянул ни к селу, ни к городу. SysV IPC вообще никогда нормально с Unix-примитивами не интегрировались.

Я предложил вариант. Дальше рассуждение по этому пути не пошло...

> condvar - гораздо более сложная вещь, чем тебе кажется.

И что, я не теперь могу её использовать в простом частном случае?

gaa ★★
()
Ответ на: комментарий от gaa

> Я предложил вариант.

Это _не_ вариант. По причине неинтегрированности в Unix, и относительной медленности.

>> condvar - гораздо более сложная вещь, чем тебе кажется.

>И что, я не теперь могу её использовать в простом частном случае?

Пока не нарисуешь соотвествующие вызовы pthread_mutex_{lock,unlock} - не стОит.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>> Я предложил вариант.

> Это _не_ вариант. По причине неинтегрированности в Unix, и относительной медленности.

Понятно.

>>> condvar - гораздо более сложная вещь, чем тебе кажется.

>> И что, я не теперь могу её использовать в простом частном случае?

> Пока не нарисуешь соотвествующие вызовы pthread_mutex_{lock,unlock} - не стОит.

Это вообще было нечто вроде псевдокода. Там и не все параметры функций правильно указывались...

Надеюсь, в логике-то я не облажался?

gaa ★★
()
Ответ на: комментарий от gaa

> поток B отвечает за условную переменную и отвечает за управление потоком A:

> while (1) { pthread_cond_wait(variable); pthread_kill(other_thread); }

зачем в этой схеме нужен парный "управляющий" поток и чем приведенный выше вариант A+B лучше вызова pthread_kill() но из основного потока?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> а) создает поток для его обработки или же

> б) помещает соединение в некую очередь

Для конкретности - я говорил о случае б)

> теперь, вопрос:

> в какое место в дочернем потоке нам нужно вставить условную переменную так, чтобы поток мог на неё оперативно отреагировать? допустим для ясности, что она сигналится бродкастом из основного потока по какому-то произошедшему в нем событию.

Напрашиваются места вызова poll, read, write, хотя для них можно использовать pthread_cancel. Дальнейшее зависит от времени реакции, которое нужно получить - если вас устраивает время реакции, составляющее максимум времени между блокирующимися вызовами, на pthread_cancel можно и остановиться (случай I/O-bound задачи) В случае длинных вычислений всё может оказаться сложнее, поэтому я и спросил про логику задачи.

Кстати, для сигнала останова отдельная condvar не нужна вообще - вполне достаточно глобального флага mustdie.

tailgunner ★★★★★
()
Ответ на: комментарий от klalafuda

> зачем в этой схеме нужен парный "управляющий" поток и чем приведенный выше вариант A+B лучше вызова pthread_kill() но из основного потока?

Ну раз нет WaitOnMultiplyObjects(вроде так пишется), то придётся разнести функциональность по разным потокам. А лучше оно тем, что можно рулить из основного потока сразу несколькими "управляющими" через condvar, не храня их список.

gaa ★★
()
Ответ на: комментарий от tailgunner

> Кстати, для сигнала останова отдельная condvar не нужна вообще - вполне достаточно глобального флага mustdie.

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

gaa ★★
()
Ответ на: комментарий от gaa

>> Кстати, для сигнала останова отдельная condvar не нужна вообще - вполне достаточно глобального флага mustdie.

>Наверно, лучше всё же обойтись без неё

Не вижу, как

> чем каждый раз проверять её значение, вставляя лишние if-ы повсюду в коде

Повсюду - не обязательно. Может быть достаточно только обработчика cancellation.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>> Наверно, лучше всё же обойтись без неё

> Не вижу, как

да, наверно действительно не обойтись.

gaa ★★
()
Ответ на: комментарий от gaa

> Ну раз нет WaitOnMultiplyObjects(вроде так пишется), то придётся разнести функциональность по разным потокам. А лучше оно тем, что можно рулить из основного потока сразу несколькими "управляющими" через condvar, не храня их список.

вам все равно придется хранить их список хотя бы для того, чтобы позвать pthread_join().

// wbr

klalafuda ★☆☆
()

Скажите, если QT такой модульный, могу я использовать ТОЛЬКО их IPC и не качать/не компилировать всё остальное?

Shadow ★★★★★
()
Ответ на: комментарий от klalafuda

>> А лучше оно тем, что можно рулить из основного потока сразу несколькими "управляющими" через condvar, не храня их список.

> вам все равно придется хранить их список хотя бы для того, чтобы позвать pthread_join().

Ну это да. Но в том моменте мы от необходимости бегать по списку избавимся.

gaa ★★
()
Ответ на: комментарий от tailgunner


> Напрашиваются места вызова poll, read, write, хотя для них можно использовать pthread_cancel.

....и как же именно мы вставим условную переменную в poll()? :)

по поводу cancellation - сложно не согласиться с PThread Primer в замечании

--- cut ---
Summary

Cancellation is the method by which one thread can kill another. Because of issues surrounding shared resources, held locks, and dynamically allocated storage, cancellation is extremely difficult to use correctly6. In Win32 and OS/2, there is virtually no way to use cancellation correctly. Cancellation can be completely avoided by implementing a polling scheme in any of the libraries, as long as we don’t have to worry about blocked threads. In POSIX, deferred cancellation combined with cleanup handlers make it merely difficult to use cancellation.

Avoid cancellation if at all possible.
--- cut ---

да, и что произойдет с объектами, которые были созданы на стеке? вызовутся ли из деструкторы при наступлении cancellation?

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

> Дальнейшее зависит от времени реакции, которое нужно получить - если вас устраивает время реакции, составляющее максимум времени между блокирующимися вызовами, на pthread_cancel можно и остановиться (случай I/O-bound задачи) В случае длинных вычислений всё может оказаться сложнее, поэтому я и спросил про логику задачи.

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

> Кстати, для сигнала останова отдельная condvar не нужна вообще - вполне достаточно глобального флага mustdie.

вполне

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от Shadow

> Скажите, если QT такой модульный, могу я использовать ТОЛЬКО их IPC и не качать/не компилировать всё остальное?

Наверно всё же придётся скомпилить ещё и qtcore, у них там всё на нём завязано. Но QtXml, QtSvg, QtGui(подавляюще крупный) и QtSql можно выкинуть.

gaa ★★
()
Ответ на: комментарий от Shadow

> Скажите, если QT такой модульный, могу я использовать ТОЛЬКО их IPC и не качать/не компилировать всё остальное?

ну по поводу "не качать" - нет, думаю, что не можете. архив распространяется all-in-one. по поводу сборки - есть определенная свобода выбора, что собирать а что нет. по поводу использования - да, конечно можете. AFAIU библиотек core+net вполне должно хватить.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Угу, спасибо.
А про спор выше - я вообще не программист... Но в свое время мне нравилась модель процессов (не потоков) в первом апаче. Родительский и дочерние вполне так удобно общались друг-с-другом.

IMHO, в простых задачах не всегда лучше потоки. И *nix до сих пор с трудом с ними работают...

Shadow ★★★★★
()
Ответ на: комментарий от klalafuda

>> Напрашиваются места вызова poll, read, write, хотя для них можно использовать pthread_cancel.

>....и как же именно мы вставим условную переменную в poll()? :)

Никак. Я такого и не предлагал. Зачем? Я говорил об использовании pthread_cancel в том случае, когда нужно асинхронное завершение. poll является cancellation point.

> по поводу pthread_cancel() - я бы как минимум сто раз подумал, стоит ли с ним связываться вообще бо потенциальных граблей с дедлоками, неосвобожденными ресурсами и пр. можно поиметь по полной программе.

Никаких возражений. Использование pthread_cancel предложено для случая, когда почему-то нельзя дождаться завершения запроса для вещей вроде изменения конфигурации или завершения работы. И чем pthread_cancel хуже pthread_kill?

> упростим задачу и разобьем работу потока на две части - ожидание запроса и обработку запроса. ожидание запроса может быть очень долгим но оно может быть прервано. обработка запроса прервана быть не может so в этом случае время обработки нам не важно.

Ну, это просто неспортивно. Ожидание запроса происходит на read/select/accept? Тогда просто делается отдельный pipe, через который основная нить отправляет команды типа "изменить конфигурацию/завершить работу". Тогда вообще никаких трюков с pthread_cancel не нужно.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Тогда просто делается отдельный pipe, через который основная нить отправляет команды типа "изменить конфигурацию/завершить работу". Тогда вообще никаких трюков с pthread_cancel не нужно.

В итоге получаем тот подход, который klalafuda ругал в самом начале разговора за перерасход файловых дескрипторов.

gaa ★★
()
Ответ на: комментарий от tailgunner

> Ну, это просто неспортивно. Ожидание запроса происходит на read/select/accept? Тогда просто делается отдельный pipe, через который основная нить отправляет команды типа "изменить конфигурацию/завершить работу". Тогда вообще никаких трюков с pthread_cancel не нужно.

правильно и такой вариант уже был выше упомянут как вариант организации "очереди сообщений". но есть и недостатки: а) синхронный read больше недоступен - нам нужен select() & K б) мы получаем по лишней паре файловых дескрипторов на каждый прерываемый поток в) код заметно усложняется. если п.а в принципе не страшно бо для организации отсутствующего в стандарте read() с таймаутом все равно придется использовать обертку с poll/select, то п.б может быть весьма накладным при большом количестве потоков а п.в геморойным в реализации -> errorprone.

предвещая предложение "давайте сделаем один pipe/socketpair на все потоки". вы уверены, что select(), одновременно вызванный на один и тот-же файловый дескрипток из разных потоков корректно отработает? лично я нет.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от gaa

> В итоге получаем тот подход, который klalafuda ругал в самом начале разговора за перерасход файловых дескрипторов.

Вообще-то я, когда писал, имел в виду 1 общий командный pipe, по которому передаются команды для _всех_ нитей (в конце концов, команда "прекратить работу" одинакова для всех нитей, не так ли?) :)

И даже если завести по pipe'у на нить, "перерасход" - _ровно_ на количество нитей в _худшем_ случае. Так вот, дескриптор pipe'а берет гораздо меньше памяти, чем стеки нити, не говоря уже о том, что и сами нити что-нибудь открывают и т.д. - т.е. в процентном отношении перерасход ресурсов невелик.

tailgunner ★★★★★
()
Ответ на: комментарий от klalafuda

> есть и недостатки: а) синхронный read больше недоступен - нам нужен select()

Этого не понял

> вы уверены, что select(), одновременно вызванный на один и тот-же файловый дескрипток из разных потоков корректно отработает? лично я нет.

Да, уверен. Если параноик, то делай команды по 1 байту :). Для завершения - хватит с избытком.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Никак. Я такого и не предлагал. Зачем? Я говорил об использовании
pthread_cancel в том случае, когда нужно асинхронное завершение.
poll является cancellation point.

> Никаких возражений. Использование pthread_cancel предложено для
случая, когда почему-то нельзя дождаться завершения запроса для
вещей вроде изменения конфигурации или завершения работы.

банальный и безобидный IMHO пример с pthread_cancel():

--- test.cpp ---
#include <cstdio>
#include <exception>
#include <iostream>
#include <pthread.h>
#include <unistd.h>

class foo {
public :
    foo() {
        std::cout << "foo ctor" << std::endl;
    }
    ~foo() {
        std::cout << "foo dtor" << std::endl;
    }
};

static void *thread(void *arg)
{
    try {
        std::cout << "Enter thread" << std::endl;
        foo f;
        sleep(5);
        std::cout << "Leave thread" << std::endl;
    } catch (const std::exception &e) {
        printf("Got std exception \'%s\'\n", e.what());
    } catch (...) {
        printf("Got unknown excetion!\n");
    }

    return 0;
}

int
main()
{
    pthread_t tid;
    std::cout << "Create thread" << std::endl;
    pthread_create(&tid, 0, thread, 0);
    sleep(2);
    std::cout << "Cancel thread" << std::endl;
    pthread_cancel(tid);
    std::cout << "Join thread" << std::endl;
    pthread_join(tid, 0);

    return 0;
}
--- test.cpp ---

$ g++ -Wall -Werror -O2 -o test test.cpp -lpthread
$ ./test
Create thread
Enter thread
foo ctor
Cancel thread
Join thread
foo dtor
Got unknown excetion!
FATAL: exception not rethrown
Aborted (core dumped)

что будем делать с этим? как бороться? :)

это кстати хорошо показывает, в чем принципиальная разница между
pthread_cancel() и pthread_kill().

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от tailgunner

> есть и недостатки: а) синхронный read больше недоступен - нам нужен select()
Этого не понял

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

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

g++ -Wall -Werror -fasynchronous-unwind-tables -O2 -o test a.c

Create thread
Enter thread
foo ctor
Cancel thread
Join thread
foo dtor
Got unknown excetion!
FATAL: exception not rethrown
Aborted

Если добавить в catch (...) "throw;", то, судя по печати, всё отрабатывает как ожидалось.

Create thread
Enter thread
foo ctor
Cancel thread
Join thread
foo dtor
Got unknown excetion!

Хотя, конечно, Си++ - это отдельная тема.

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.