Цитата
Для начала давайте определимся, что любой объект с состоянием(для простоты рассматриваем класс в ООП) это так или иначе и есть конечный автомат.
Да. Тред, работающий на одноядерном процессоре - тоже конечный автомат, вернее не тред, а вся эта тредовая ОС

Цитата
Чтобы состояние менялось атомарно и состояние менялось строго в соответствии с графом(алгоритмом) при вызове методов из разных потоков(т.е. упростим до понятия "одновременно") вводятся мьютексы, сериализирующие изменение состояния.
Потоков
нет. Поток у нас один. Мютексов тоже ессно нет. Но есть приоритеты событий.
Цитата
Первое и самое главное ограничение это необходимость редизайна задачи(объекта, конечного автомата) таким образом, чтобы при выделении процессорного времени она быстренько run to completion. Следовательно мы должны проектировать наш объект(конечный атомат) таким образом, чтобы все изменения в состоянии происходили строго из одной точки входа(функции, которую дёргает SST планировщик). И обязательно принять условие, что только планировщик будет вызывать эту функцию.
Этим занимается компилятор. Я не могу сам вызвать функцию-обработчик - компилятор мне этого не позволит.
И это не ограничение, это другой стиль программирования, и очень классный!

Цитата
Бог та другая задача сделает что-то(вызовет метод), что изменит состояние первой задачи, которая находится в процессе смены состояния! Выполнение то было прервано на пол пути, где-то посередине ребра графа состояний конечного автомата. Бог знает в каком месте.
Другим задачам запрещено менять состояние данной задачи. Любая коммуникация между задачами происходит через
очереди(каналы, пайпы, fifo - называйте как хотите). Если задача А хочет изменить состояние задачи Б, тогда задача А ставит этот запрос в очередь, и как только задача Б будет готова принять эти изменения - она это сделает. Всем этим занимается не пользователь, а компилятор вместе с планировщиком.
Цитата
Таким образом да, благо
Цитата
даря одному потоку мы уже имеем последовательное выполнение и якобы не нуждаемся в мьютексах, которые как раз и созданы для сериализации доступа.
У Вас для сериализации доступа используются тяжеленные мютексы и громадный стек, а у нас - легковесные быстрые очереди, довольно не редко lockfree.
Цитата
Таким образом интерфейс задачи(объекта) превращается не в привычный набор методов, а в набор сообщений которые можно посылать объекту.
Да, но это не ограничение, а другой стиль. Зачем сделали NodeJS, если есть PHP, Python и другие динамические языки. Разве ради того, чтобы загонять программистов в ограничения? Да на Javascripte такое можно сделать, что Php-шнику или Питонщику не снилось, и работать это будет очень быстро.
Цитата
Из всего этого следуют требования очень вдумчивой расстановки приоритетов задач, что по дизайну заставит вас подпиливать задачи под систему, что нарушиает инкапсуляцию, увеличивает завязку частей системы друг на друга. Хотя-бы в части форматов этих очередей с сообщениями.
Расстановка приоритетов нужна как в асинхронной оси, так и в многопоточной синхронной. Да, можно конечно выдавать таймкванты длительностью 100мкс и не париться, но это будет жуткий тормознутый монстр с бешенным оверхедом и скорее всего такая система не будет адекватно реагировать на прерывания.
Нежели просто грамотно расставить приоритеты прерываний и пользовательских задач. Мало того, приоритет может меняться динамически(что у меня часто и происходит), но об этом позже, не будем пока лесть в дебри.
Да и большинство задач юзера имеют одинаковый приоритет. С приоритетами надо поработать только с системными задачами - та же шина SPI, Uart, Dma, итд. Ну и естественно - с прерываниями, они тоже могут друг друга прерывать(вытеснять)

У пользователя обычно всего 1-2-3 приоритета.
Цитата
В системе появляется много функторов(делегаты ваши) которые циркулируют туда-сюда...
Да, они там повсюду. Но это такой стиль и он очень хорошо себя зарекомендовал.
Цитата
Для их применения вам придется делать обёртку либо каждый раз изобретать велосипед. О чем вам уже не только я говорил.
Часто готовый софт либо что-то делает одно(типа MP3, jpeg итд) и свободно ложится на SST. Либо имеет возможность работать в асинхронном неблокирующем стиле, хоть и через костыли (как, например Linux в отличии от FreeBSD). Но если софт жестко завязан на потоки и без них там никак - в мусорку этот софт. Например Апач - без PHP он бесполезный. А нафик PHP, если есть NodeJS? И нафиг тогда сервер(бесполезная прослойка), если на этом же Node такой сервер пишеться за 20 минут(на установку и настройку апача уйдет не меньше), а остальное время будет потрачено на бизнес-логику, которое могло быть потрачено на ту же логику на PHP? Значит втопку апач.
Точно так же и другой софт. Если там нет Async Nonblocking IO - дорога ему в мусорку, rm -rf *

Цитата
По этим причинам SST это далеко не панацея, а хитрое название для давно и хорошо известного автоматного подхода
https://ru.wikipedia.org/wiki/%D0%90%D0%B2%...%BD%D0%B8%D0%B5способ сэкономить немного памяти/немного проца за счет немалых изменений в архитектуре системы.
Конечно это не панацея, и это автомат. Но довольно продвинутый, там кейсом не обойдешься, ибо простейшая задача будет иметь 100 и более кейсов

Цитата
Как видим на примере современных ОС в реальном мире побеждает симбиоз потоков и разделения времени с событиями(асинхронный IO тому пример).
На чем наверно можно и сделать окончательный вывод )
Причина чисто историческая. Так исторически сложилось, что программирование и железо у нас императивное. Хотя есть более совершенные техники, например функциональное программирование, но они непонятны нынешним программистам.
Точно так же и с потоками - так исторически получилось, что ОС у нас многопоточные, навязывают нам такой стиль. Переписать то сами ОС можно запросто, только переписывать весь софт, который уже под них существует у человечества сил не хватит.
Поэтому выход один - допиливать в существующие ОС async IO, планировку процессов оставлять в sync-стиле, а сами приложения проектировать в async-стиле. Да любая нормальная софтина сейчас в async-стиле делается, тот же Qt, Node итд итп.
За всю историю, сколько я пишу на QT, я создавал треды только тогда, когда надо было в фоне непрерывно, на всем доступном процессорном времени что-то считать, например FFT. Остальное IO свободно работало в главном потоке(там, где и GUI) и система работала шустро. FFT-поток получал данные через очередь, никаких мютексов - подключил свой велосипед под названием SPSC lock-free queue. Благо, у STL для этого есть atomic-переменные, и у Интела есть их аппаратная поддержка.
И то этот поток - вынужденная мера, тк в QT нет приоритетов событий. Если бы был приоритет - я бы просто поставил FFT приоритет ниже, чем в GUI и все, был бы абсолютно тот же эффект.
Гляньте на язык Java, вернее на приложения, которые на нем написаны. Как они тормозят. На любом железе тормозят жутко. Потому что там тонны потоков(хоть ява и позволяет программировать asnyc, особенно сейчас). И посмотрите, как летает однопоточный асинхронный Javascript в Node

Цитата
Конечно же такой подход тоже является NP полным и позволит вам теоретически решить любую задачу.
Асинхронный подход позволяет решить любую задачу(равно, как и синхронный). Только это решение в 90-95% случаев лучше, красивее, эффективнее, чем на потоках. Примеров тому масса, они повсюду.
Или вот тот же мой сервак, который отправляет пользователю рандом 100 раз в секунду. Асинхронное решение простое, натуральное, и отправляет действительно строго каждые 10мс.
CODE
var timer;
function on_socket_closed(){
n_connections--;
clearInterval(timer);
}
// Periodically send random data to client
timer = setInterval(function(){
var str;
for(var i=0; i<100; i++){
str+= String.fromCharCode(Math.random()*256);
}
socket.write(str);
}, 10);
В то время как синхронное решение горбатое, с жутким джиттером, тк сами вызываем функцию sleep непонятно когда, да еще и send может блокироваться.
CODE
char buffer[4096];
int i,r;
while(1){
for(i=0; i<100; i++)buffer[i] = rand();
r = send(sock, buffer, 100, 0);
if(r<=0){
perror("Thread_connection: socket error");
break;
}
usleep(10000);
};
Что бы было меньше джиттера, нам придется создать еще один поток - таймер, создать семафор, в таймере его устанавливать(инкрементировать) а в отправителе декрементировать. Жуть - 2 потока только ради того, чтобы периодически отправлять набор байт

А что будет, если будет реальная задача? Когда таймеров понадобится штук 5? Даже представить сложно, как это все будет тормозить и глючить...