metaclass: (Default)
[personal profile] metaclass
Как известно, в программировании есть несколько проклятых тем. Т.е. задач, которые сами по себе просты, но их общего (повторно-используемого, кросс-платформенного, не заставляющего глаза течь кровью) решения не бывает и приходится каждый раз мутить какие-то велосипеды.
Одна из таких тем: прерывание длительных и блокирующих операций. Смежная - показ прогресса для таких операций. Вот, например, в контексте скалы: http://ru-scala.livejournal.com/36634.html
Почему эта тема проклята?
Во-первых, прерывание означает либо два потока, либо callback изнутри операции, вызывающий проверку наличия ввода от пользователя (Application.DoEvents/Application.ProcessMessages). Средний разработчик от многопоточности и callback бежит как от огня.
Во-вторых, i/o операции изначально сами по себе блокирующие. Всякие там чтения из сокетов, файлов(на сгнившей файловой системе примонтированной с выключенного сервера), rs232-портов с забытыми таймаутами и прочего зла. Реализация асинхронного i/o - жесточайшее уныние, что с overlapped, что с completion ports, что с select и прочими epoll.
В уютной сишечьке или недалеко от них ушедших C++ и Delphi - это по крайней мере, помещается в мозг, в дотнетах же, жабах, рантаймах хаскеля и прочих порождениях геенны огненной - либо авторы рантайма озаботились прерыванием операций, либо изобретение велосипеда вырождается в чад угара и лавирования между GC и разными уровнями представления данных.
Во-третьих, "у меня на столе все работает". Когда сервера не выключаются, сеть работает, диски без бэдов и железо отвечает вовремя - операции отрабатывают быстро, или можно их выполнять мелкими блоками и проверять какие-нибудь флаги отмены.

В-четверых, часто эти операции завернуты в десятки слоев чужих библиотек, например, "выполнение запроса к БД и выборка неизвестного количества миллионов записей, потому что база не знает сколько записей подпадает под условие". Если повезет - метод "прервать и свалится с исключением в потоке выполнения запроса" будет в API и даже после его применения внутренние структуры данных не превратятся в кашу. Если нет - то только убивать себя о стену.

Date: 2013-04-16 07:28 pm (UTC)
From: [identity profile] http://users.livejournal.com/_slw/
в rt-11 прерывание операций было сделанно и работало зашибись.
как и асинхронный ввод-вывод, кстати.

Date: 2013-04-16 08:41 pm (UTC)
From: [identity profile] antontsau.livejournal.com
ну и кстати нет. У каждого уважающего себя драйвера была критическая часть, которую даже прервать было нельзя. Соответственно если оно косело в этом месте (одно слово считалось, а на втором железо обвисло), а афтырь случился мудак и не предусмотрел, то валилось все вообще. Хотя и редко, там ничего сложного в такие критические части писать было не принято.

Date: 2013-04-16 10:18 pm (UTC)
From: [identity profile] http://users.livejournal.com/_slw/
ну если железо косело, то вся система могла раком встать -- там память и шина общие были.
ну и как бы "автор -- мудак" не считается, от этого защты нет.
а на все остальное в драйвере была точка ABORT для отмены операции.
ну и да, у контроллера должен был быть соответсвующий битик в CSR, ну так у всех стандартных устройств и было (нет, MX -- не стандартное, это вообще недоразумение)

Date: 2013-04-17 08:04 am (UTC)
From: [identity profile] antontsau.livejournal.com
ну не совсем уж косело, но скажем обещало дать байт, а не отдавало, и крутился драйвер в каком-то тупом цикле ждал какой-нибудь бит готовности. А вструмлять массу проверок, таймаутов и прочего в критическую чаксть драйвера тоже считалось зело нехорошо. По уму конечно надо было все такое тут же выносить в некритическую чать... но тогда могло и не успеть, если этот байт слишком быстро лез. Чего-то вспоминается, что такая проблема была при напейсании драйвера винта для двк3-4, там контроллер был шибко умный и быстрый, но шибко глюкавый, и постоянно завешивался.

Date: 2013-04-17 08:09 am (UTC)
From: [identity profile] http://users.livejournal.com/_slw/
что значит обещало и не отдавало?
обещало -- это обычно 000200 в CSR. как после этого можно не отдать что-то в дата?
более того, хорошим тоном не в цикле крутиться, а 000100 в CSR поставить и отдаться до прерывания.

а контроллер винта по DMA работать должен.
как и дисковода (если он не MX, разумеется. но MX жить не должен).
он, собственно и работал, кажется, потому как загрузка из пульта с него была возможна без написания программ, просто программированием регистров.

Date: 2013-04-17 08:42 am (UTC)
From: [identity profile] antontsau.livejournal.com
обещало - это прерывание дернуло, а бит не выставило. Что делать? Втупую вернуться, валиться с ошибкой, попробовать еще разок, крутиться ждать? Зависит от афтыря.

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

Не помню уже в чем там была проблема, но как-то не получалось. Контроллер не тот что от СМ, а тот что от ДВК, он там вуууууумный был как вутка.

Date: 2013-04-17 08:49 am (UTC)
From: [identity profile] http://users.livejournal.com/_slw/
> обещало - это прерывание дернуло, а бит не выставило. Что делать?

с железкой разбираться.

да я понял, что для MFM винтов, а не для будущих антен.

Date: 2013-04-16 07:53 pm (UTC)
From: [identity profile] justy-tylor.livejournal.com
Свои таски, которые будут работать в параллельных тредах, кидать в очередь юзеринтерфейсного треда проценты выполнения, а также прерываться по команде - пишутся за день на любой привычной платформе. Почему из коробки на этих платформах только жабы и черви - вопрос философский.

Что же касается асинхронщины, то она вся на таких заплатках к говнопосиксу и винапи, что её не обернуть в разумную форму без потерь. А других ядер у нас нет.

Date: 2013-04-17 03:45 am (UTC)
From: [identity profile] thedeemon.livejournal.com
Чтобы свои таски прерывались по команде, они должны решить проблему с залипающими операциями, об этом ребе и говорит.

В винапи асинхронный IO как раз первичен, а синхронный сделан поверх оного, насколько я знаю. Другой вопрос, что использовать все привыкли синхронный, ибо проще.

Date: 2013-04-17 09:39 am (UTC)
From: [identity profile] justy-tylor.livejournal.com
Только в ядре. На деле - до асинхронного ReadFile добираемся через синхронный CreateFile.

Date: 2013-04-16 08:02 pm (UTC)
From: [identity profile] falcrum.livejournal.com
Это да: задача "как корректно срубить зависший поток по таймауту" обычно... :(

Date: 2013-04-16 08:29 pm (UTC)
From: [identity profile] vit-r.livejournal.com
Средний разработчик от многопоточности и callback бежит как от огня.

Средний разработчик об этом не знает. А если знает, то не правильно. Как-то в группе, делавшей реалтайм "на системе, которая всё берёт на себя", нашёлся только один человек, который, нет не проверил, а просто понял, что там с прерываниями и семафорами написано.

Date: 2013-04-16 11:11 pm (UTC)
From: [identity profile] w00dy.livejournal.com
И что случилось? Группа схлопнулась в точку? :)

Date: 2013-04-17 03:46 am (UTC)
From: [identity profile] thedeemon.livejournal.com
Пришлось всех убить.

Date: 2013-04-17 04:59 am (UTC)
From: [identity profile] vit-r.livejournal.com
Ничего не случилось. Разработка шла по плану, деньги активно экономили, набирая людей дешёвых.

Правда, слышал, на полевых испытаниях реальность сказала "Привет!". А что они делали потом, фиг знает. Может тул какой купили хитрый, может кого-то с мозгами наняли. Но последнее врядли.

Date: 2013-04-16 08:37 pm (UTC)
From: [identity profile] enternet.livejournal.com
Не вижу ничего проклятого. Есть правильные шаблоны разработки таких вещей. Просто правильность должна соблюдаться на всех уровнях реализации.

Примеры (от балды про винду):
низкий уровень - WaitForMultipleObjects и ваши волосы станут белыми. Может быть даже и пушистыми, но это уже как повезет - не все драйверы порождают все нужные события.
средний уровень - например, на винде в данный момент глупо писать свой TCP-сервер, потому как есть ряд системных сервисов, через которые все необходимое можно получить в готовом, высокопроизводительном виде.
высокий уровень - следование идеологии разработки таких вещей в выбранной среде и понимание её ограничений. Т.к. рантайм всегда ограничен.

Date: 2013-04-16 08:46 pm (UTC)
From: [identity profile] metaclass.livejournal.com
В винде есть что-нибудь позволяющие произвольные бинарные протоколы по TCP слушать?
Я только про http.sys в курсе, но он для веб-серверов вроде же.

Date: 2013-04-16 11:35 pm (UTC)
From: [identity profile] w00dy.livejournal.com
http.sys он от iis. А я так понимаю ребе говорит об wcf и прочих штучках которые умеют поднимать канал через кучу всяких транспортов. Или сразу об этих самых транспортах.

Date: 2013-04-17 04:51 am (UTC)
From: [identity profile] enternet.livejournal.com
И то, и то. Если речь идет о заранее жестко заданном бинарном протоколе на ТЦП, то да, ничего лучше и проще чем воспользоваться обертками над IO Completion Ports нет. Собственно там и писать нечего, всё уже написано и разжевано до нас.

А если речь идет о своем протоколе, совместимом с http, то тут-то у нас появляется большой выбор готовых сервисов, начиная с http.sys и далее по всяким wcf/wws/etc. Ведь http по большому счету - это всего лишь текстовый заголовок перед данными.

Date: 2013-04-17 04:58 am (UTC)
From: [identity profile] enternet.livejournal.com
Если говорить про _свои_ протоколы, то на данный момент ничего лучше чем делать протокол http-совместимым - нет. Это делается совершенно элементарно и из этого получаются замечательные бонусы. И вообще, http.sys - крайне производительная штука, очень понравился, рекомендую.

Ну а для закрытых бинарных протоколов есть вагон готовых оберток и примеров по работе с IO Completion Ports.

Date: 2013-04-17 06:36 am (UTC)
From: [identity profile] arush-damage.livejournal.com
В смысле?
С тисипи же бинарный поток приходит, что вам еще надо?

Date: 2013-04-17 06:46 am (UTC)
From: [identity profile] metaclass.livejournal.com
В смысле, что тут рассказывают про то, что в винде есть готовые сервисы для этого. Ну типа как (x)inetd в линуксах. Т.е., я по аналогии с http.sys предполагаю, что где-то есть мега-сервис, к которому можно подцепится и реализовать TCP-сервер.

Впрочем, судя по всему, имелось в виду наличие API для асинхронного обмена и его оберток.

Date: 2013-04-17 06:53 am (UTC)
From: [identity profile] arush-damage.livejournal.com
Ну апи то в наличии, а обертки зачем?
Логика сервера достаточна проста, зачем там обертки?

Date: 2013-04-16 11:34 pm (UTC)
From: [identity profile] w00dy.livejournal.com
Многопоточность, watchdog (убивающий подвисшие потоки, как самый крайний вариант) плюс делать таски чтобы они могли себя прерывать в определённых точках (проверять флаг). Если делал один раз, то ничего сложного имхо.

Date: 2013-04-17 03:27 am (UTC)
From: [identity profile] smalgin.livejournal.com
Не нужно убивать себя об стену, нужно для каждой асинхронной операции четко выписать state change, после чего по таймауту тупо откатывать этот state change назад (rollback) или вперед (failure/failover/whatever). В большинстве случаев не нужно эмулировать транзакцию, достаточно, чтобы достигалось state consistency перед и после вызова, а это гораздо легче. Finite state machines, мать их. Само собой, если вдруг выяснится, что вызов какой-то функции имеет поганые и недокументированные side effects, то без убийства об стену не обойтись.... ну дак способом, как известно, цыган и хату спалил...

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

Date: 2013-04-17 05:08 am (UTC)
From: [identity profile] metaclass.livejournal.com
Для своих потоков и вообще своего кода - это еще куда ни шло, там можно сделать по человечески, и FSM и async i/o и ожидания.

Date: 2013-04-17 05:16 am (UTC)
From: [identity profile] sergiej.livejournal.com
Просто если собрать толпу лучших разработчиков мира, и попросить согласовать как эта проблема должна решаться, то они скорее поубивают друг друга, чем найдут конценсус.

Date: 2013-04-17 06:20 am (UTC)
From: [identity profile] volodymir-k.livejournal.com
не-а

они просто разделятся и будут писать свои форки

уже так и случилось миллион раз

Date: 2013-04-17 06:22 am (UTC)
From: [identity profile] sergiej.livejournal.com
О тот и речь, поэтому и нет на "системном" уровне решения - любое будет "плохим" для "большей половины".

Date: 2013-04-17 05:30 am (UTC)
From: [identity profile] trueblacker.livejournal.com
ящитаю, примитивный клиент-сервер на неблокирующих сокетах - обязательное упражнение для всякого программиста, претендующего на продвинутость

Date: 2013-04-17 06:54 am (UTC)
From: [identity profile] arush-damage.livejournal.com
Нельзя!
Это подрывает позиции производителей фрэймворков! %))

Date: 2013-04-17 06:15 am (UTC)
From: [identity profile] volodymir-k.livejournal.com
> Во-вторых, i/o операции изначально сами по себе блокирующие.

В юниксе да.
В винде-нт изначально нет, сразу асинхронно, а для win32 сделали блокирующие прокладки.

> Реализация асинхронного i/o - жесточайшее уныние

Вкусовщина. Если у вас мозги заточены на read(buf) и больше не гнутся.

> callback изнутри операции, вызывающий проверку наличия ввода от пользователя (Application.DoEvents/Application.ProcessMessages).

Изучите, что такое флаги и как они могут выставляться.

Впрочем не надо, не будете конкурентом.

Date: 2013-04-17 06:33 am (UTC)
From: [identity profile] metaclass.livejournal.com
>Изучите, что такое флаги и как они могут выставляться.
О каких флагах идет речь?

Date: 2013-04-17 06:39 am (UTC)
From: [identity profile] berezovsky.livejournal.com
CreateThread? О_О

Date: 2013-04-22 11:15 am (UTC)
From: [identity profile] volodymir-k.livejournal.com
ладно, поясню

"callback изнутри операции, вызывающий проверку наличия ввода" -- неправильная организация потоков

message consumer thread должен запустить поток операции и передать ему объект-семафор "is_interrupted"

потом при "наличии ввода" message consumer thread должен выставить семафор

на который поток с операцией должен поглядывать и прерываться, если ему удобно

семафор ваще-то вполне определённая штука, поэтому обычно юзают не системный semaphore, а обычный булев флаг-переменная, тока у него должен быть модификатор volatile

архитектурно, НЕЛЬЗЯ вводить ОС-специфическую логику в операцию

как вы этого не заметили -- не понимаю; если заметили и не делаете, то ваще не понимаю

Date: 2013-04-22 11:20 am (UTC)
From: [identity profile] metaclass.livejournal.com
А почему OS-специфичное вводить нельзя?

Булев флаг с volatile допустимо, конечно, но у меня расчетные потоки обычно спят, ожидая либо таймаута, либо одного из пары событий - выход или сообщение про необходимость выполнить некую операцию.

Date: 2013-04-22 12:05 pm (UTC)
From: [identity profile] kiryl.livejournal.com
> семафор ваще-то вполне определённая штука, поэтому обычно юзают не системный semaphore

за "изобретение" собственных средств "синхронизации" нужно гнать ссаными тряпками.

> а обычный булев флаг-переменная, тока у него должен быть модификатор volatile

volatile, внезапно, не защищает от переупорядочивания обращений к памяти процессором.

Date: 2013-04-18 07:11 am (UTC)
From: [identity profile] anonim-legion.livejournal.com
Речь же идет о сторонних библиотеках.

Date: 2013-04-22 11:19 am (UTC)
From: [identity profile] volodymir-k.livejournal.com
речь о сторонних библиотеках идёт только в одном месте, что они не вставляют проверки на нечто левое в свой код
таки да! проблема и костыли известны

потом речь идёт идёт о своём коде, где "callback изнутри операции, вызывающий проверку наличия ввода от пользователя"
что очевидно не случай библиотек

Profile

metaclass: (Default)
metaclass

April 2017

S M T W T F S
      1
2345678
9101112 131415
16171819202122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 25th, 2025 08:01 am
Powered by Dreamwidth Studios