OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Воскресенье, 15 Июнь, 2025 20:20

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 23 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Активные компоненты
СообщениеДобавлено: Четверг, 23 Ноябрь, 2006 10:44 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2461
Откуда: Россия, Томск
Привет всем!

Я тут работаю на BlackBox, пишу программу для наблюдения за температурой (условно говоря). Суть в том, что по COM-порту приходят данные, я их интерпретирую и добываю информацию о температуре и других параметрах системы управления отоплением дома. Для этого дела я написал подсистему "Mate", а данные отображаю на специализированных компонентиках (MateViews.View). На один параметр - один компонентик. Пользователь может расположить вьюшки в тексте или на форме, снабдив соответствующими комментариями, чтобы не забыть, где что отображается. Столкнулся с несколькими интересными проблемами, которыми и хочу поделиться.

Принципиальная особенность моей подсистемы в том, что компоненты в ней "активные". В том смысле, что они не ждут действий от пользователя, с ними и так все время что-то происходит. Даже если человек уйдет и сутки не будет появляться. Источником активности служит специальный Services.Action, который следит за поступлением новой информации из порта связи. При поступлении очередной порции данных рассылается уведомление о новом значении параметра и все компоненты, отображающие данный параметр, соответствующим образом обновляют свой внешний вид.

Такая взаимосвязь означает, что где-то обязательно должен существовать глобальный список компонентов для оповещения. И к этому списку должен иметь доступ тот самый экземпляр Services.Action, который инициирует рассылку сообщений. (Этот доступ не обязательно будет выражаться в прямой ссылке, но, тем не менее, в каком-то виде он должен быть налажен. Я сделал хук, благодаря чему работа с портом абсолютно не зависит от клиентского кода.)

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

Если компонент из текста удалить, запись должна прекратиться. Или, например, если закрыть ненужное окно с сохраняемыми параметрами, запись тоже должна прекратиться, не так ли? И в самом деле, документ больше не открыт, глобальных ссылок на него и на компоненты, входящие в его состав, нет, значит, он будет уничтожен "сборщиком мусора", и запись данных прекратится...

Нет, к сожалению, это не так. Я столкнулся с тем, что запись продолжается. Более того, теперь ее невозможно остановить, поскольку после закрытия окна щелкнуть мышкой по компоненту для остановки записи уже не представляется возможным. Запись идет, растет объем используемой памяти. Остается только два варианта - перезапуск BlackBox или выгрузка модуля MateAutoSave (с парой сообщений об ошибках).

Используя знания, накопленные за годы работы в Delphi, я принялся искать какие-нибудь оповещения типа OnClose или OnDelete, которые бы позволяли отреагировать на закрытие документа или удаление компонента из контейнера, но ничего подобного не нашел. Постепенно во мне родилось понимание того, что объекты принципиально пассивны в том, что касается времени их жизни. Не только на уровне управления памятью (процедура NEW и сборщик мусора), но и на уровне фреймворка. Например, если объект удалили из документа (нажав клавишу BackSpace), то он ничего не узнает об этом. Он будет продолжать существовать как ни в чем ни бывало, ведь на него все еще имеется ссылка - в буфере "Undo"! И он будет считать, что находится в том же самом документе, из которого удален (переменная context не изменяется). А уж если на него есть глобальная ссылка, то он будет существовать до тех пор, пока не выгрузят модуль с этой ссылкой. Следовательно, будет существовать и весь документ, "удерживаемый" context'ом.

Что касается моих компонентов, то они "активны". Благодаря всем этим разбирательствам я понял принципиальную характеристику "активного компонента" - самостоятельное управление временем своей жизни. Активный компонент сам может решать, когда ему прекратить свое существование. А пока компонент активен, на него есть как минимум одна глобальная ссылка (в модуле Services).

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

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

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

Пользуясь случаем, хочу передать привет тем форумчанам, которые утверждали, что без нитей (threads) невозможно нормально работать с COM-портами, сокетами и прочими последовательными коммуникациями. Работаю очень просто и без проблем. : )


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 23 Ноябрь, 2006 11:29 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Александр, спасибо за поучительный рассказ!

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

Я тоже сталкивался с проблемой регистрации объектов в глобальных списках. Зарегистрировав объект в списке, мы создаем на него глобальный якорь. Но таким образом список не может узнать сам, когда объект более не нужен! N-е время назад я написал процедурку, которая позволяет искать на низком уровне все ссылки на объект (как это делает Kernel.Mark) и сделал в модуле-регистраторе некий высокоуровневый сборщик мусора, который периодически проверял, остались ли на объекты внешние ссылки, и если нет, то исключал их из списка - а далее их "добивал" обычный сборщик :-)
Сейчас, переписывая рантайм, я позаимствовал одну хорошую идею, которая есть в .NET - слабые указатели (weak pointers). Слабый указатель - это ссылка на объект, которая не является якорем. Когда нам нужно работать с объектом, мы можем запросить у слабого указателя обычный указатель. Если нам вернут NIL, то мы видим, что объект уже собран сборщиком мусора.

А вообще, с многопоточностью все равно работать гораздо лучше, нежели без нее :-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 23 Ноябрь, 2006 12:18 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2461
Откуда: Россия, Томск
Илья Ермаков писал(а):
По поводу определения, когда объект больше не показывается на экране... Здесь можно пойти таким путем - через модуль Windows искать открытые кадры, связанные с отображением. Если их нет, то можно останавливаться...

Вы, наверное, предлагаете пойти тем же путем, что Views.Omnicast (я не смотрел, как он реализован, но суть в том, что рассылается сообщение всем видимым View). Проблема с этой процедурой в том, что ее оповещения приходят только к тем View, которые хотя бы частично видны на экране. Я думаю, где-то существует их глобальный список для целей прорисовки, и по этому списку делается проход. Но активный объект должен быть активен даже если он не отображается. Если он скрыт из поля зрения из-за прокрутки, он все равно должен периодически сохранять текущие значения параметров. Так что наличие фрейма - не показатель, если только вы не возьметесь утверждать, что для каждого View, встроенного в потенциально отображаемую часть документа, всегда есть хотя бы один фрейм. Включая View, свернутые в Fold?

По-моему, просто фреймворк не разрабатывался для соответствия тем требованиям, которые предъявляют активные объекты. Работа с Models, Views и документами построена на тех же принципах, что работа с памятью, а память принципиально пассивна. Есть место для развития, но лучше оставить существующее простое решение. Главное - понять, что за ним стоит. При большом желании с моей стороны, наверное, можно было бы разработать специализированный контейнер или wrapper, отслеживающий удаление активных компонентов. И, кстати, создать глобальный базовый абстрактный тип для таких компонентов. Хм...

Илья Ермаков писал(а):
Я тоже сталкивался с проблемой регистрации объектов в глобальных списках. Зарегистрировав объект в списке, мы создаем на него глобальный якорь. Но таким образом список не может узнать сам, когда объект более не нужен! N-е время назад я написал процедурку, которая позволяет искать на низком уровне все ссылки на объект (как это делает Kernel.Mark) и сделал в модуле-регистраторе некий высокоуровневый сборщик мусора, который периодически проверял, остались ли на объекты внешние ссылки, и если нет, то исключал их из списка - а далее их "добивал" обычный сборщик :-)
Сейчас, переписывая рантайм, я позаимствовал одну хорошую идею, которая есть в .NET - слабые указатели (weak pointers). Слабый указатель - это ссылка на объект, которая не является якорем. Когда нам нужно работать с объектом, мы можем запросить у слабого указателя обычный указатель. Если нам вернут NIL, то мы видим, что объект уже собран сборщиком мусора.

Идея слабых указателей в самом деле решила бы эту проблему (заодно добавив новые?). Еще один вариант решения - счетчик ссылок: как только остается ровно одна ссылка, мы знаем, что это ссылка из глобального списка, и объект можно выбрасывать. К сожалению, оба эти решения требуют переделки рантайм-системы. А вот высокоуровневый сборщик мусора мне бы мог понравиться, если он эффективен. Можете поделиться кодом?

Илья Ермаков писал(а):
А вообще, с многопоточностью все равно работать гораздо лучше, нежели без нее :-)

Конечно, лучше! : )
Осталось только договориться о том, что значит "лучше", не так ли? ; )


Последний раз редактировалось Александр Ильин Четверг, 23 Ноябрь, 2006 12:33, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 23 Ноябрь, 2006 12:23 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Цитата:
...выгрузка модуля с парой сообщений об ошибках...


Посмотрите как выгружаются модули: CommObxStreamsServer и CommObxStreamsClient. Там все "сервисы" удаляются "вручную".
Код:
   ...

   PROCEDURE Stop*;
   BEGIN
      WHILE processors # NIL DO
         processors.stream.Close; Services.RemoveAction(processors);
         processors := processors.succ
      END;
      IF server # NIL THEN
         Services.RemoveAction(server);
         server.listener.Close;
         server := NIL;
         StdLog.String("server: server stopped"); StdLog.Ln
      END
   END Stop;

CLOSE
   Stop   (* prevent the server from trapping after module unloading *)
END CommObxStreamsServer.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 23 Ноябрь, 2006 12:32 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2461
Откуда: Россия, Томск
Сергей Губанов писал(а):
Цитата:
...выгрузка модуля с парой сообщений об ошибках...


Посмотрите как выгружаются модули: CommObxStreamsServer и CommObxStreamsClient. Там все "сервисы" удаляются "вручную".

Да, и это еще раз подтверждает, что без глобальных списков/переменных не обойтись.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные компоненты
СообщениеДобавлено: Четверг, 23 Ноябрь, 2006 13:02 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Александр Ильин писал(а):
Пользуясь случаем, хочу передать привет тем форумчанам, которые утверждали, что без нитей (threads) невозможно нормально работать с COM-портами, сокетами и прочими последовательными коммуникациями. Работаю очень просто и без проблем. : )


Это я утверждал. Можно увидеть код?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 23 Ноябрь, 2006 13:08 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
"Сборщиком" - поделюсь, сейчас только код откопаю, нарежу и заверну :-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Четверг, 23 Ноябрь, 2006 13:22 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Во, он у меня даже в товарном виде есть... В еще не вышедшей 0.6-й версии MT, в модуле MtMem.
Вот, выкладываю исходник и документацию на модуль:
http://blackbox.metasystems.ru/download/forum/MtMem06.rar


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные компоненты
СообщениеДобавлено: Пятница, 24 Ноябрь, 2006 01:35 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2461
Откуда: Россия, Томск
Vlad писал(а):
Александр Ильин писал(а):
Пользуясь случаем, хочу передать привет тем форумчанам, которые утверждали, что без нитей (threads) невозможно нормально работать с COM-портами, сокетами и прочими последовательными коммуникациями. Работаю очень просто и без проблем. : )


Это я утверждал. Можно увидеть код?

Конечно! : )
Только я его оформлю в отдельную тему.
Даже написал побольше комментариев в исходники по такому случаю. : )


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные компоненты
СообщениеДобавлено: Пятница, 24 Ноябрь, 2006 13:02 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Александр Ильин писал(а):
Конечно! : )
Только я его оформлю в отдельную тему.
Даже написал побольше комментариев в исходники по такому случаю. : )


Кода, непосредственно работающего с COM-портом я так и не увидел.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные компоненты
СообщениеДобавлено: Пятница, 24 Ноябрь, 2006 17:37 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2461
Откуда: Россия, Томск
Vlad писал(а):
Кода, непосредственно работающего с COM-портом я так и не увидел.

Какой вы скучный товарищ! Самая суть вопроса, использовать или не использовать нити, заключается в способе периодического получения новых данных, не так ли? Нить использовать "проще" потому, что там можно написать "глухой" цикл, не берущий в расчет параллельно выполняемые задачи. Кооперативная многозадачность "сложнее" потому, что цикл приходится делать "открытым", постоянно самовозобновляемым на каждой итерации. Я вам продемонстрировал, что такой открытый цикл очень просто реализуется на основе Services.Action. Нет нужды ничего блокировать, нет и дополнительной сложности в реализации клиентского кода.

Чтож, если вас в самом деле интересуют технические детали работы непосредственно с портом, то пожалуйста.

Вы знакомы с модулем CommV24? Это стандартный модуль для работы с COM-портами, входящий в поставку BlackBox. В ту же ветку "Последовательные коммуникации" я выложил слегка доработанный мною вариант этого модуля. Доработка сводится к возможности создания потока CommStreams.Stream для работы с портом. CommAction далее использует этот (или любой другой) поток.

В результате одна и та же программа может без перекомпиляции работать как с любым COM-портом, так и через TCP/IP или что угодно еще, для чего напишете драйвер на основе CommStreams.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Активные компоненты
СообщениеДобавлено: Пятница, 24 Ноябрь, 2006 18:38 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Александр Ильин писал(а):
Vlad писал(а):
Кода, непосредственно работающего с COM-портом я так и не увидел.

Какой вы скучный товарищ!


Я предпочитаю термин "прагматичный".

Александр Ильин писал(а):
Самая суть вопроса, использовать или не использовать нити, заключается в способе периодического получения новых данных, не так ли? Нить использовать "проще" потому, что там можно написать "глухой" цикл, не берущий в расчет параллельно выполняемые задачи.


Нет не совсем так. Устраивать кооперативную многозадачность там, где где больше подходит вытесняющая, это еще то извращение, но я готов с ним смириться. Претензии по поводу "нормальности" работы с COM-портом в одном потоке прежде всего упираются в эффективность. Решение, при котором из порта в цикле выковыриваются данные, даже если их там нет, я "нормальным" признать не могу. Потому что при достаточно малом временном интервале между опросами порта мы грузим процессор (лично в этом убеждался, даже при интервале в детятки миллисекунд, простое обращение к COM-порту на K6-400 грузило процессор чуть ли не на половину), а при достаточно большом интервале - увеличивается время реакции системы на приход новых данных.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 24 Ноябрь, 2006 19:41 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2461
Откуда: Россия, Томск
Хорошо, только я не понял вот чего: предложенное мной решение является достаточно парагматичным на ваш взгляд или нет? В любом случае, в конечном итоге процессор у нас один, сколько бы нитей мы на нем ни запустили. Ведь все нити на самом деле выполняются по очереди, а не одновременно, так что вытесняющая многозадачность на нижнем уровне сводится к кооперативной с той только разницей, что в кооперативной многозадачности каждая задача сама решает, когда отдать процессор другим задачам, а в вытесняющей вытеснение производится принудительно в произвольный момент времени. В этом смысле вытесняющая многозадачность - это просто такой способ писать программы. Способ писать. Один из способов, а не что-то принципиально иное. Поэтому, я считаю, весь вопрос при выборе того или иного способа заключается в том, будет ли у нас в результате достаточно прозрачная структура программы, т.е. можно ли адекватно имитировать многозадачность, не вводя дополнительных сущностей. Другими словами, есть ли простой способ написать программу с аналогичными возможностями, но без концептуальной путаницы и внезапных прерываний выполнения, требующих механизмов синхронизации и т.п. Я считаю, что продемонстрировал такой способ. Вы согласны с тем, что я его продемонстрировал и что он действительно достаточно прост?

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

Если вы пытаетесь сказать, что "засыпающая" до прихода данных нить будет потреблять меньше процессорных ресурсов, чем периодически проверяющая на пустоту буфер приема драйвера, то вы правы. Что касается исключительной дороговизны опроса буфера из вашего примера, это скорее всего недостатки ОС либо драйвера. В таком случае ваш способ может оказаться единственно работоспособным, так что вы снова правы - в контексте того конкретного примера. Я же пытаюсь рассуждать в несколько более общем плане.

Не менее прагматично, но прагматично в ином плане.

Я считаю, что вытесняющая многозадачность может быть необходима во "враждебном окружении" вроде ОС MS Windows. "Враждебность" его заключается в том, что параллельно работают много программ, написанных неизвестно кем и как. Любая из этих программ может "зависнуть" и сломаться. Естественно, мы не хотим, чтобы такой сбой привел к краху всей системы, мы хотим закрыть "плохую" программу и спокойно продолжить работу с остальными. В этом случае конкурентность дает необходимую независимость. Но внутри своей-то собственной программы неужели нельзя навести порядок, чтобы все долгоиграющие процессы были разбиты на кооперативные подзадачи и не увеличивали время реакции?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 24 Ноябрь, 2006 21:50 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Александр Ильин писал(а):
предложенное мной решение является достаточно парагматичным на ваш взгляд или нет?


В рамках BB - вполне.

Александр Ильин писал(а):
В любом случае, в конечном итоге процессор у нас один,


В моем компе - два.

Александр Ильин писал(а):
В этом смысле вытесняющая многозадачность - это просто такой способ писать программы. Способ писать. Один из способов, а не что-то принципиально иное.


Ну да. А еще можно писать ОО или процедурно. Разница принципиальная. Хотя я не буду утверждать, что одно однозначно лучше другого.

Александр Ильин писал(а):
Вы согласны с тем, что я его продемонстрировал и что он действительно достаточно прост?


Да, я согласен, что конкретно этот случай, если не оглядываться на особенности конкретной ОС и масштабируемость, достаточно прост и не имеет фатальных недостатков по сравнению с многопоточным вариантом.

Александр Ильин писал(а):
Если вы пытаетесь сказать, что "засыпающая" до прихода данных нить будет потреблять меньше процессорных ресурсов, чем периодически проверяющая на пустоту буфер приема драйвера, то вы правы.


Да, именно это я и хотел сказать.

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


Можно. Вопрос только в том, насколько "ручное разбиение" будет удобнее "необходимости синхронизации". Эта тема уже обсуждалась вот здесь: http://bbforum.metasystems.ru/viewtopic ... c&start=60
И будет ли такое ручное разбиение вообще иметь смысл, при наличии в системе более одного процессора. А сегодняшняя тенденция компьютеростроения - это именно наращивание числа ядер, потому что частоту наращивать уже некуда.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 24 Ноябрь, 2006 23:26 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 485
Откуда: KZ
Цитата:
И будет ли такое ручное разбиение вообще иметь смысл, при наличии в системе более одного процессора. А сегодняшняя тенденция компьютеростроения - это именно наращивание числа ядер, потому что частоту наращивать уже некуда.


Будет, если есть не один компьютер. А если мы хотим заставить программу работать быстрее, логоично использовать для этого ресурсы нескольких компьютеров. Сейчас два компьютера с одним процессором стоят дешевле, чем один с двумя. К тому же на многопроцессорной системе в этом случае можно запустить несколько копий.

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


Последний раз редактировалось Alexander Shiryaev Суббота, 25 Ноябрь, 2006 06:20, всего редактировалось 2 раз(а).

Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пятница, 24 Ноябрь, 2006 23:52 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
По поводу считывания из COM-порта - насколько я краем левого уха глядел модуль CommV24, там нет никакого постоянного опроса порта, а просто используются процедуры асинхронного чтения порта как файла из WinApi. Мы ж не на ассемблере пишем, асинхроника для ввода-вывода есть уже на уровне системных функций.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Суббота, 25 Ноябрь, 2006 01:24 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2461
Откуда: Россия, Томск
Vlad писал(а):
Александр Ильин писал(а):
Если вы пытаетесь сказать, что "засыпающая" до прихода данных нить будет потреблять меньше процессорных ресурсов, чем периодически проверяющая на пустоту буфер приема драйвера, то вы правы.

Да, именно это я и хотел сказать.

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

Vlad писал(а):
Александр Ильин писал(а):
Но внутри своей-то собственной программы неужели нельзя навести порядок, чтобы все долгоиграющие процессы были разбиты на кооперативные подзадачи и не увеличивали время реакции?


Можно. Вопрос только в том, насколько "ручное разбиение" будет удобнее "необходимости синхронизации". Эта тема уже обсуждалась вот здесь: http://bbforum.metasystems.ru/viewtopic ... c&start=60
И будет ли такое ручное разбиение вообще иметь смысл, при наличии в системе более одного процессора. А сегодняшняя тенденция компьютеростроения - это именно наращивание числа ядер, потому что частоту наращивать уже некуда.

Да, я читал ту ветку.
: ))


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Суббота, 25 Ноябрь, 2006 02:12 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2461
Откуда: Россия, Томск
Илья Ермаков писал(а):
По поводу считывания из COM-порта - насколько я краем левого уха глядел модуль CommV24, там нет никакого постоянного опроса порта, а просто используются процедуры асинхронного чтения порта как файла из WinApi. Мы ж не на ассемблере пишем, асинхроника для ввода-вывода есть уже на уровне системных функций.

Вы правы, Илья, асинхроника есть в WinApi.

Тут могу сделать замечание о том, что, к сожалению, асинхронная работа не заложена в интерфейс модуля CommV24. Процедуры ReceiveByte и ReceiveBytes - блокирующие. Само их объявление не предполагает никакой возможности того, что запрошенное число байт не будет прочитано или будет прочитано "потом". Это еще ладно, можно перед чтением вызывать Available и читать не больше того, что реально уже доступно. Самая главная проблема - в процедурах SendByte и SendBytes. Они тоже не предполагают асинхронной работы. Обычно делается так: передаешь указатель на буфер и количество записываемых байт, а тебе возвращают, сколько байт реально удалось записать. Так вот, здесь ничего не возвращают. Поэтому приходится ждать, пока запишут все. Поэтому приходится записывать помаленьку.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 27 Ноябрь, 2006 14:38 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Alexander Shiryaev писал(а):
Сейчас два компьютера с одним процессором стоят дешевле, чем один с двумя.


Ты давно в компьютерном магазине был? ;) Когда несколько месяцев назад заказывали новый рабочий комп, цена вопроса (одно ядро против двух, при прочих равных) была 30$. Понятно, что я не получаю автоматом комп в два раза быстрее, но практика показывает, что второя ядро не простаивает все время. Кстати, даже несколько лет назад двухпроцессорные Маки были заурядным явлением, причем позиционировались они не как сервера, а как обычные рабочие лошадки.

Alexander Shiryaev писал(а):
Для N-процессорной системы лучше, чтобы общее количество системных тредов было равно N, остальная же часть программы всё равно должна быть асинхронной.


Что значит "все равно"? Чтобы при добавлении еще одного процессора переписывать все нафиг?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Понедельник, 27 Ноябрь, 2006 14:43 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 18:38
Сообщения: 1857
Илья Ермаков писал(а):
нет никакого постоянного опроса порта, а просто используются процедуры асинхронного чтения порта как файла из WinApi. Мы ж не на ассемблере пишем, асинхроника для ввода-вывода есть уже на уровне системных функций.


И что это меняет? Асинхронный в/в на виндах подразумевает лишь то, что вместо постоянного опроса порта, приходится постоянно опрашивать флажок завершенности в/в.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 23 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2025, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB