Проклятая тема
Apr. 16th, 2013 10:17 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Как известно, в программировании есть несколько проклятых тем. Т.е. задач, которые сами по себе просты, но их общего (повторно-используемого, кросс-платформенного, не заставляющего глаза течь кровью) решения не бывает и приходится каждый раз мутить какие-то велосипеды.
Одна из таких тем: прерывание длительных и блокирующих операций. Смежная - показ прогресса для таких операций. Вот, например, в контексте скалы: 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 и даже после его применения внутренние структуры данных не превратятся в кашу. Если нет - то только убивать себя о стену.
Одна из таких тем: прерывание длительных и блокирующих операций. Смежная - показ прогресса для таких операций. Вот, например, в контексте скалы: 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 и даже после его применения внутренние структуры данных не превратятся в кашу. Если нет - то только убивать себя о стену.
no subject
Date: 2013-04-17 06:15 am (UTC)В юниксе да.
В винде-нт изначально нет, сразу асинхронно, а для win32 сделали блокирующие прокладки.
> Реализация асинхронного i/o - жесточайшее уныние
Вкусовщина. Если у вас мозги заточены на read(buf) и больше не гнутся.
> callback изнутри операции, вызывающий проверку наличия ввода от пользователя (Application.DoEvents/Application.ProcessMessages).
Изучите, что такое флаги и как они могут выставляться.
Впрочем не надо, не будете конкурентом.
no subject
Date: 2013-04-17 06:33 am (UTC)О каких флагах идет речь?
no subject
Date: 2013-04-17 06:39 am (UTC)no subject
Date: 2013-04-22 11:15 am (UTC)"callback изнутри операции, вызывающий проверку наличия ввода" -- неправильная организация потоков
message consumer thread должен запустить поток операции и передать ему объект-семафор "is_interrupted"
потом при "наличии ввода" message consumer thread должен выставить семафор
на который поток с операцией должен поглядывать и прерываться, если ему удобно
семафор ваще-то вполне определённая штука, поэтому обычно юзают не системный semaphore, а обычный булев флаг-переменная, тока у него должен быть модификатор volatile
архитектурно, НЕЛЬЗЯ вводить ОС-специфическую логику в операцию
как вы этого не заметили -- не понимаю; если заметили и не делаете, то ваще не понимаю
no subject
Date: 2013-04-22 11:20 am (UTC)Булев флаг с volatile допустимо, конечно, но у меня расчетные потоки обычно спят, ожидая либо таймаута, либо одного из пары событий - выход или сообщение про необходимость выполнить некую операцию.
no subject
Date: 2013-04-22 12:05 pm (UTC)за "изобретение" собственных средств "синхронизации" нужно гнать ссаными тряпками.
> а обычный булев флаг-переменная, тока у него должен быть модификатор volatile
volatile, внезапно, не защищает от переупорядочивания обращений к памяти процессором.
no subject
Date: 2013-04-18 07:11 am (UTC)no subject
Date: 2013-04-22 11:19 am (UTC)таки да! проблема и костыли известны
потом речь идёт идёт о своём коде, где "callback изнутри операции, вызывающий проверку наличия ввода от пользователя"
что очевидно не случай библиотек