Pull to refresh

Comments 37

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

Извините, но на мой взгляд, многоуровневая вложенность IF'ов есть — неудачные примеры создания классов.
А чем это плохо? Мне так было удобнее писать… А с точки зрения скорости, думаю, оптимизатор разберётся.
Плохо это по следующим причинам:
— тяжело читать
— тяжело менять логику (не гибко)

Вы описали подход к решению конкретной задачи выложив «деревянную» реализацию.
В вашей статье ценны следующие моменты:
— узкие места
— способы обработки
А они в свою очередь теряются в большом количестве плохого кода.
(например, по коду у вас разбросаны флаги, которые определяют состояние, например fStateLock. И понять логику работы коды без комментариев автора очень тяжело. И ещё тяжелее поверить в работоспособность данного решения. Так что, по сути я говорю о том, что ваш код очень тяжело сопровождать и развивать)
А на мой взгляд, в таком виде легче менять логику всего что касается низкоуровнего программирования, winapi в частности. В приведённых листингах, по большому счёту, вообще альтернативы нет. Что насчёт флагов, так то и не флаги вовсе, а поля(сокращения от английской нотации, так в Delphi почти повсеместно), не зря готовый исходник прикреплен к началу. Посмотреть на рабочий итог в нём и можно.
Отложите свой код куда-нить в чулан и через полгода попробуйте внести новую фичу поставив рядом кого-нибудь из друзей, который будет WTFcount инкрементировать. Будет интересно узнать значение этого счетчика в конечном итоге.
Я всё понимаю. Но опять таки. Исходник выложен только с той целью, что если какому-то хардкорщику из ряда системных программистов придётся столкнутся с асинхронной очередью в сокетах для него это будет подарок. Даже так как он есть. Этот топ нацелен на достаточно узкую, интересную и сложную тему, а не на пропаганду чистописания. А WTFcount чуть более чем 9000 сомнения не вызывает =)
Так и не нашел описания методов _AddRef и _Release. Если это — стандартные методы IUnknown, то автор вообще в курсе, почему они начинаются с подчеркивания?

Подчеркивание как бы намекает, что программист не должен вызывать эти методы самостоятельно, если используемый им язык правильно поддерживает COM-интерфейсы. А Object Pascal их поддерживает, вызывая _AddRef при каждом появлении интерфейсной ссылки на объект, и _Release при ее исчезновении.

Так что лучше пересмотрите использование _AddRef и _Release в коде.
Я использую интерфейсы не для реализации COM объектов, а для того чтобы не создавать ручками класс где ведётся учёт ссылок, это опять таки нужно чтобы следить за памятью в событийно ориентированном программировании. С внутренней организацией интерфейсов в Delphi я знаком более чем.
Тогда зачем используются подчеркивания?

PS Собрал я вместе все куски кода, а он все равно не компилируется… Чего же не хватает?
А если серьезно, то почему мы должны догадываться, что ты там используешь? Где описание переменных, в конце концов-то?! особенно меня интересует тип переменной ProtoArray.
Этот архив скоро исчезнет, а статья еще долго будет жить.
У меня была схожая задача. Ушло все в мультиплексирование, а событийное всякое выделил на уровень выше, уже после того как информация с сокета прочитана.

Сейчас постараюсь понять ваше решение, видно что-то понимаете, но Project3 Unit9 уже отпугивает…
Это просто код с рабочего сервера откинутый в отдельный проект ради иллюстрации.
Боюсь, что меня не хватит читать его. Ради всего святого, ну зачем вам COM? Он там все загадил… Ну и читать было бы легче если бы комментарии были хоть какие-то. И или я чего-то не понял, или там не waitformultiplyevent должен быть а waitforsingleobject… там-же только 1 ивент?

Быть может там где это внедрено — так лучше, но как отдельный проект выглядит оно не очень, ИМХО.

P. S. Впрочем, рад приветствовать умных людей на хабре, сил моих не хватает читать про хостинг и хабраэффект.
Я не использовал COM и автоматизацию… Интерфейсы тут — это хитрый ход для отслеживания объектов в очереди.
CoInitialize — очень хитро. Я прочитал статью и так и не понял сути, где оно все мультиплексируется, где обрабатывается. Прочитать исходники не осилил. Реквестирую картинки, как для школьников 5ого класса с гуманитарным уклоном).

P. S. если используете хитроту — комментируйте ее обязательно.
CoInitialize вызвана при старте потоков чтобы обработчики событий которые вызовет класс могли использовать COM внутри себя… Интерфейсы в дельфи ничем на прямую с COM не связаны… По этому я их использовал для учёта того используется объект где-то в других потоках или нет.
Честно сказать не расчитывал, что его будет много желающих прочесть… Просто реализаций таких сокетов на просторах очень мало, и я подумал что неплохо будет добавить.
И все правильно подумали, но понять это решение очень сложно.
Я так и не понял в чем разница от обычных сокетов(. тех над которыми accept, recv, send, close…
Такс… Суть в том что обычные сокеты при большом пуле открытых соединений (актуально для не UDP протоколов) начинают тратить время на переключение контекстов потоков их обрабатывающих. Поняв это в Microsoft сделали IOCP, использование которой в дельфи я и продемонстрировал. IOCP это очередь сообщений на уровне ядра построенная специальным образом, так чтобы с помощью ограниченного кол-ва потоков обработать неограниченное кол-во запросов IO для любых конечных точек (сокеты файлы и т.д.).
waitformultiplyevent… где-то обнаружилась информация, что его использовать предпочтительнее в любом случае.
Я так понимаю, этот код — часть какой-то ИС, которая наверное еще и где-то в гос. секторе работает?
Вероятно которая еще лет 10 разрабатывалась, и будет еще столько же… И тот кто будет после вас писать этот код умрет от радости)).

Я это к тому, что название функций, используемые методы очень сильно вводят в заблуждение.
Ну вот как я могу понять что кома тут и нет, что Event — один Event, а не еще какая-то хитрота 80 lvl-а?

P. S. все мы мастера ругать чужой код, и это полезно, не принимайте близко к сердцу.
Да я и не принимаю то =) Это часть стрим-сервера чат+видео+аудио. Сервер высоко нагруженный. Решил выложить, т.к. IOCP на дельфи оказалось в новьё. И никто ни слухом ни духом как его там прикручивать. По крайней мере из широкого круга программистов.
Ох, как-то не привычно что Делфи еще жив где-то кроме как гос. сектора)) и редких исключений.
Кстати с выходом последний версии значительно прибавил привлекательности… =)
Если используется ThreadPool то для чего были созданы целых три отдельных нитки для обработки событий?
Насколько я понимаю, события можно обрабатывать при помощи RegisterWaitForSingleObject.
Не обратил внимание, что автор самостоятельно реализует TreadPool вместо использования стандартного…
Да RegisterWaitForSingleObject тут бы подошла отлично если бы поддерживала сокеты. В целом идея отличная, сегодня её проверю. Спасибо! Насчёт пула — я не нашёл подходящего в стандартной библиотеке, к сожалению…
1. RegisterWaitForSingleObject — работает с событиями (Event). В том числе с socketEvent'ами

2. Под пулом я имел в виду в том числе WinApi функцию a href=«msdn.microsoft.com/en-us/library/windows/desktop/aa363484(v=vs.85).aspx»>BindIoCompletionCallback
2 — Я видел такой альтернативный вариант реализации. Тоже попробую. Там интересно посмотреть как будет обстоять дело с постановкой в очередь своих собственных сообщений и с выборкой их оттуда.
В методе TIOCPSocketProto.Read:
при формировании исключения sErrorRead_WSARecv сбрасывается блокировка, а при исключении sErrorRead_GetMem — остается в заблокированном состоянии.
Есть такой недочёт=) Приятно что хоть кто-то оставляет комментарии по делу…
А недочет то исправили?
Ну как и ожидалось — код с мэйло-обменника благополучно исчез. Автор, перезалейте архив с исходниками куда-нибудь ещё, пожалуйста.
Sign up to leave a comment.

Articles