ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Воскресенье
19 мая
339113 Топик полностью
fk0, легенда (06.07.2012 11:09, просмотров: 483) ответил bialix на Изобретаю велосипед на тему асинхронных функций. Предлагаю вам начинать кидаться гнилыми помидорами и тухлыми яйками, либо дополнить своими дельными соображениями если таковые имеются. Вобщем, чем плохая тема для тяпницы?
Ответ длинный и со ссылками. Сходу в голову приходит http://code.google.com/p/protothread -- там именно так и сделано, можно вызвать функцию из другой "нити", заблокироваться в её ожидании, и она тоже может заблокироваться в ожидании чего-либо... в это время будут выполняться другие функции. По-сути кооперативная многозадачность, плюс некий RPC поверх (для "вызовов" между потоками или "сопрограммами"). Про protothreads в частности. Они родились только как попытка избавиться от стека в недоконтроллерах типа PIC18, AVR (tiny) и т.п. При наличии более-менее большого (десятки КБайт) объёма ОЗУ можно подумывать и о нормальном стеке. Он, на самом деле, не такой уж и большой нужен часто, буквально десятки байт. Большой он нужен лишь при вызове отдельных функций -- и тут неплохо бы задуматься на тему longjmp и их вызова на отдельном, большом общем стеке, с обязательным ожиданием возврата, без блокировки (переключения задач). Ещё локальные переменные, большого объёма, но тут просто стоит использовать malloc или что-то вроде того. Так при наличии стека все ужасы protothreads (которые им. Adam Dunkels) уже не имеют значения. Речь именно о кооперативной многозадачности. С ручным переключением потоков (сопрограммы) или планировщиком (при вызове блокируемой функции, например). Что плохого в автоматах. В основном они дают не слишком эффективный код и лишний расход энергии, где это критично. Автоматы нужны в основном на уровне проектирования. Далее либо они кодируются как есть (методом им. Шалыто, например), либо трансформируются в event-driven программу, либо вовсе в блок-схему, которая кодируется влоб. A речь о fifo и т.п. -- это уже разные методы межпроцессного взаимодействия. И они действительно нужны. Метод Шалыто применённый влоб, например, имеет недостатки, наподобии известной "инверсии приоритетов" -- когда сообщение отправляется какому-либо автомату и вызывается его функция, то фактически исполнение переключается на него. Разговоры о асинхронности от того, что хотелось бы в данном случае отложить исполнение до окончания выполнения текущей функции другого автомата, например. Или вторая очевидная проблема -- рекурсия, в предельном случае, например, автомат не может генерировать сообщения сам для себя (в методе Шалыто) -- стек переполнится. Здесь тоже нужно отложенное исполнение. И какие-либо из методов применяемых в полноценных вытесняющих ОС помогут. И прерывания в этом же контексте, зачастую из обработчика прерываний не вызвать функцию автомата напрямую, причины разные (разные стеки, функция может блокироваться и т.п.), но суть одна, что нужно отложенное исполнение. FIFO с событиями не всегда лучший метод. Возникает первый же вопрос -- возможное переполнение fifo (quantum leaps rtos использует такой метод). Вместо этого в большинстве случаев достаточно будет "события", которое или возникло, или нет (булевая переменная). При условии, что возникшие события обрабатваются быстрей, чем они возникают снова, разумеется. С Миро Самеком согласен. Но с другой позиции: сама идея взять и в лоб писать "линейные алгоритмы" -- дурная. Нужен этап проектирования и тут возникают автоматы. Или блок-схемы. Одно достаточно просто трансформируется в другое (Шалыто показал, см. softcraft.ru). А идея protothreads основана на том, что дескать проектировать автоматы нудно и сложно, мы тут по-простому сейчас как-нибудь (это ключевое слово) в голове придумаем алгоритм и он может быть сразу заработает. При наличии же алгоритма в виде автомата или блок-схемы уже нет принципиальной разницы как его кодировать, в protothread или по switch-технологии. В ассемблере будет примерно одно и то же. И потом может оказаться, что автомат более читаемый и понимаемый в итоге. Но в связке с многозадачными ОС, protothreads и т.п. связана ещё одна вещь. В отличии от event-driven программ или автоматов, protothreads и большинство RTOS для микроконтроллеров не позволяют ожидать более чем одного события одновременно (для одного потока). Автомат, например, практически всегда в одном состоянии реагирует на несколько событий. Можно задаться вопросом, как один и тот же алгоритм, изначально заданный в виде автомата, можно перенести на protothreads тогда? Ответ в общем известен. Во-первых тут начинаются всяческие ухищрения, например, вместо того, чтобы просто ожидать события в заблокированном состоянии поток регулярно просыпается от таймера и вручную их проверяет (метод "поллинга", ага, не далеко ушли от big loop). Или возникают несколько потоков, каждый из них ожидает своё событие и выполняет свой переход в автомате. Нельзя сказать, что такие программы хорошо читаются и понимаются, что содержат минимум ошибок и т.п. Protothreads и обычные потоки весьма обманчивы. О планировщике. Он всегда нужен, если нет совсем уж ручного переключения между потоками. А его нет, если есть хоть какой-то механизм "синхронизации" между асинхронными потоками. Хоть упомянутые события, хоть fifo. Весь любой поток может заблокироваться в ожидании события. И какая-то часть программы при возникновении события должна запустить заблокированный поток. Callbacks же вызывают проблему "инверсии приоритетов". И невозможны, например, при исполнении в прерывании и т.п. Дальше буков много ниасилил. Лично я вижу перспективу в event-driven программировании, но из головы такие алгоритмы не пишутся и изначально проектируются автоматным методом. Разумеется нужен какой-то планировщик, для запуска функций по факту возникновения событий (если функции не вызываются напрямую, а это не всегда возможно). Это для замены автоматов по switch-технологии. Преимущества -- более эффективное использование CPU, где потребление энергии критично. Отсутствие вытеснения плюс и минус одновременно. В микроконтроллере какая-то ограниченная форма вытеснения будет всегда -- прерывания (сигналы на PC в unix). Вытесняющая ОС нужна, но скорей в форме с ограниченным множеством мало зависимых между собой параллельных процессов. Да, и ещё многие вытесняющие RTOS забывают, что в них не будут нормально работать библиотечные функции языка C. Такие RTOS хорошо подходят, IMHO, для демонстрации студентам параллельных процессов на примере моргающих с разной скоростью светодиодов, но не для практических задач. Практически многие библиотеки, разве что за исключением redhat'овской newlib имеют проблемы с многозадачностью. Но и в newlib нужна явная связка ОС и библиотеки. Интересно nuttx смотрится, там эти проблемы решены.
[ZX]