Comments 38
В данной статье кратко рассмотрены, на мой взгляд, удачные приёмы создания классов для событийного программирования.
Извините, но на мой взгляд, многоуровневая вложенность IF'ов есть — неудачные примеры создания классов.
А чем это плохо? Мне так было удобнее писать… А с точки зрения скорости, думаю, оптимизатор разберётся.
Плохо это по следующим причинам:
— тяжело читать
— тяжело менять логику (не гибко)
Вы описали подход к решению конкретной задачи выложив «деревянную» реализацию.
В вашей статье ценны следующие моменты:
— узкие места
— способы обработки
А они в свою очередь теряются в большом количестве плохого кода.
(например, по коду у вас разбросаны флаги, которые определяют состояние, например fStateLock. И понять логику работы коды без комментариев автора очень тяжело. И ещё тяжелее поверить в работоспособность данного решения. Так что, по сути я говорю о том, что ваш код очень тяжело сопровождать и развивать)
— тяжело читать
— тяжело менять логику (не гибко)
Вы описали подход к решению конкретной задачи выложив «деревянную» реализацию.
В вашей статье ценны следующие моменты:
— узкие места
— способы обработки
А они в свою очередь теряются в большом количестве плохого кода.
(например, по коду у вас разбросаны флаги, которые определяют состояние, например fStateLock. И понять логику работы коды без комментариев автора очень тяжело. И ещё тяжелее поверить в работоспособность данного решения. Так что, по сути я говорю о том, что ваш код очень тяжело сопровождать и развивать)
А на мой взгляд, в таком виде легче менять логику всего что касается низкоуровнего программирования, winapi в частности. В приведённых листингах, по большому счёту, вообще альтернативы нет. Что насчёт флагов, так то и не флаги вовсе, а поля(сокращения от английской нотации, так в Delphi почти повсеместно), не зря готовый исходник прикреплен к началу. Посмотреть на рабочий итог в нём и можно.
Отложите свой код куда-нить в чулан и через полгода попробуйте внести новую фичу поставив рядом кого-нибудь из друзей, который будет WTFcount инкрементировать. Будет интересно узнать значение этого счетчика в конечном итоге.
Я всё понимаю. Но опять таки. Исходник выложен только с той целью, что если какому-то хардкорщику из ряда системных программистов придётся столкнутся с асинхронной очередью в сокетах для него это будет подарок. Даже так как он есть. Этот топ нацелен на достаточно узкую, интересную и сложную тему, а не на пропаганду чистописания. А WTFcount чуть более чем 9000 сомнения не вызывает =)
Так и не нашел описания методов _AddRef и _Release. Если это — стандартные методы IUnknown, то автор вообще в курсе, почему они начинаются с подчеркивания?
Подчеркивание как бы намекает, что программист не должен вызывать эти методы самостоятельно, если используемый им язык правильно поддерживает COM-интерфейсы. А Object Pascal их поддерживает, вызывая _AddRef при каждом появлении интерфейсной ссылки на объект, и _Release при ее исчезновении.
Так что лучше пересмотрите использование _AddRef и _Release в коде.
Подчеркивание как бы намекает, что программист не должен вызывать эти методы самостоятельно, если используемый им язык правильно поддерживает COM-интерфейсы. А Object Pascal их поддерживает, вызывая _AddRef при каждом появлении интерфейсной ссылки на объект, и _Release при ее исчезновении.
Так что лучше пересмотрите использование _AddRef и _Release в коде.
Я использую интерфейсы не для реализации COM объектов, а для того чтобы не создавать ручками класс где ведётся учёт ссылок, это опять таки нужно чтобы следить за памятью в событийно ориентированном программировании. С внутренней организацией интерфейсов в Delphi я знаком более чем.
Тогда зачем используются подчеркивания?
PS Собрал я вместе все куски кода, а он все равно не компилируется… Чего же не хватает?
А если серьезно, то почему мы должны догадываться, что ты там используешь? Где описание переменных, в конце концов-то?! особенно меня интересует тип переменной ProtoArray.
PS Собрал я вместе все куски кода, а он все равно не компилируется… Чего же не хватает?
А если серьезно, то почему мы должны догадываться, что ты там используешь? Где описание переменных, в конце концов-то?! особенно меня интересует тип переменной ProtoArray.
В посте есть ссылка на архив.
У меня была схожая задача. Ушло все в мультиплексирование, а событийное всякое выделил на уровень выше, уже после того как информация с сокета прочитана.
Сейчас постараюсь понять ваше решение, видно что-то понимаете, но Project3 Unit9 уже отпугивает…
Сейчас постараюсь понять ваше решение, видно что-то понимаете, но Project3 Unit9 уже отпугивает…
Это просто код с рабочего сервера откинутый в отдельный проект ради иллюстрации.
Боюсь, что меня не хватит читать его. Ради всего святого, ну зачем вам COM? Он там все загадил… Ну и читать было бы легче если бы комментарии были хоть какие-то. И или я чего-то не понял, или там не waitformultiplyevent должен быть а waitforsingleobject… там-же только 1 ивент?
Быть может там где это внедрено — так лучше, но как отдельный проект выглядит оно не очень, ИМХО.
P. S. Впрочем, рад приветствовать умных людей на хабре, сил моих не хватает читать про хостинг и хабраэффект.
Быть может там где это внедрено — так лучше, но как отдельный проект выглядит оно не очень, ИМХО.
P. S. Впрочем, рад приветствовать умных людей на хабре, сил моих не хватает читать про хостинг и хабраэффект.
Я не использовал COM и автоматизацию… Интерфейсы тут — это хитрый ход для отслеживания объектов в очереди.
CoInitialize — очень хитро. Я прочитал статью и так и не понял сути, где оно все мультиплексируется, где обрабатывается. Прочитать исходники не осилил. Реквестирую картинки, как для школьников 5ого класса с гуманитарным уклоном).
P. S. если используете хитроту — комментируйте ее обязательно.
P. S. если используете хитроту — комментируйте ее обязательно.
CoInitialize вызвана при старте потоков чтобы обработчики событий которые вызовет класс могли использовать COM внутри себя… Интерфейсы в дельфи ничем на прямую с COM не связаны… По этому я их использовал для учёта того используется объект где-то в других потоках или нет.
Честно сказать не расчитывал, что его будет много желающих прочесть… Просто реализаций таких сокетов на просторах очень мало, и я подумал что неплохо будет добавить.
И все правильно подумали, но понять это решение очень сложно.
Я так и не понял в чем разница от обычных сокетов(. тех над которыми accept, recv, send, close…
Такс… Суть в том что обычные сокеты при большом пуле открытых соединений (актуально для не UDP протоколов) начинают тратить время на переключение контекстов потоков их обрабатывающих. Поняв это в Microsoft сделали IOCP, использование которой в дельфи я и продемонстрировал. IOCP это очередь сообщений на уровне ядра построенная специальным образом, так чтобы с помощью ограниченного кол-ва потоков обработать неограниченное кол-во запросов IO для любых конечных точек (сокеты файлы и т.д.).
waitformultiplyevent… где-то обнаружилась информация, что его использовать предпочтительнее в любом случае.
Я так понимаю, этот код — часть какой-то ИС, которая наверное еще и где-то в гос. секторе работает?
Вероятно которая еще лет 10 разрабатывалась, и будет еще столько же… И тот кто будет после вас писать этот код умрет от радости)).
Я это к тому, что название функций, используемые методы очень сильно вводят в заблуждение.
Ну вот как я могу понять что кома тут и нет, что Event — один Event, а не еще какая-то хитрота 80 lvl-а?
P. S. все мы мастера ругать чужой код, и это полезно, не принимайте близко к сердцу.
Вероятно которая еще лет 10 разрабатывалась, и будет еще столько же… И тот кто будет после вас писать этот код умрет от радости)).
Я это к тому, что название функций, используемые методы очень сильно вводят в заблуждение.
Ну вот как я могу понять что кома тут и нет, что Event — один Event, а не еще какая-то хитрота 80 lvl-а?
P. S. все мы мастера ругать чужой код, и это полезно, не принимайте близко к сердцу.
Да я и не принимаю то =) Это часть стрим-сервера чат+видео+аудио. Сервер высоко нагруженный. Решил выложить, т.к. IOCP на дельфи оказалось в новьё. И никто ни слухом ни духом как его там прикручивать. По крайней мере из широкого круга программистов.
Если используется ThreadPool то для чего были созданы целых три отдельных нитки для обработки событий?
Насколько я понимаю, события можно обрабатывать при помощи RegisterWaitForSingleObject.
Насколько я понимаю, события можно обрабатывать при помощи 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. Под пулом я имел в виду в том числе WinApi функцию a href=«msdn.microsoft.com/en-us/library/windows/desktop/aa363484(v=vs.85).aspx»>BindIoCompletionCallback
В методе TIOCPSocketProto.Read:
при формировании исключения sErrorRead_WSARecv сбрасывается блокировка, а при исключении sErrorRead_GetMem — остается в заблокированном состоянии.
при формировании исключения sErrorRead_WSARecv сбрасывается блокировка, а при исключении sErrorRead_GetMem — остается в заблокированном состоянии.
Ну как и ожидалось — код с мэйло-обменника благополучно исчез. Автор, перезалейте архив с исходниками куда-нибудь ещё, пожалуйста.
Sign up to leave a comment.
Windows Sockets, IOCP и Delphi