Перейти к содержанию
    

LOL : чуть дальше "Но реально не применяю :-), как-то не жмёт пока обычный switch()... "
По крайней мере я не пользуюсь этой возможностью не потому, что я о ней не знаю :-)

Мне просто не нужен эффект от неё, а я с какого-то фига стараюсь не использовать нечто очень специфическое - хотя иногдасамому непонятно почему. Используют же работающие с IAR его всякие красивости и в ус не дуют.

Впрочем, потихоньку прорывает, недавно таки поставил диапазонный case там, где он был удобен, чуть раньше локальную (вложенную) функцию использовал там, где она очень просилась.

В подобных же темах часто обсуждается как бы выжать ещё немного объёма и скорости и в таком месте вычисляемый goto вполне в строку. Имеет общие черты как функцй, возвращющих указатели на фунции, так и switch

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Интересно, а как сделать с набором параллельно работающих конечных автоматов (без RTOS) долго работающую задачу, требующую активного участия процессора ? Например, работу с FAT (сектор может читаться значительное время) или рендеринг экрана для UI (тоже небыстро). Разбивать на отдельные этапы некрасиво и неудобно, а иначе задача будет блокировать другие на долгое время.

 

С подобными вещами не сталкивался, так как у меня обычно много мелких задач и отрабатываются они мгновенно, либо без участия

процессора - большую часть времени процессор спит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Интересно, а как сделать с набором параллельно работающих конечных автоматов (без RTOS) долго работающую задачу, требующую активного участия процессора ? Например, работу с FAT (сектор может читаться значительное время) или рендеринг экрана для UI (тоже небыстро). Разбивать на отдельные этапы некрасиво и неудобно, а иначе задача будет блокировать другие на долгое время.

Да, есть некоторая проблема. Там, где обращение к УВВ гробит интерфейс пользователя, делаем упреждающее чтение в память при включении устройства (ну типа Windows :) ). Там где это невозможно... ну работали же раньше с дискетами? Часики, песочек...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Интересно, а как сделать с набором параллельно работающих конечных автоматов (без RTOS) долго работающую задачу, требующую активного участия процессора ? Например, работу с FAT (сектор может читаться значительное время) или рендеринг экрана для UI (тоже небыстро). Разбивать на отдельные этапы некрасиво и неудобно, а иначе задача будет блокировать другие на долгое время.
Разбивать на этапы, и других вариантов особо и нет...

Ну или хитрое разделение с задачами выполняемыми в прерываниях.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Разбивать на этапы, и других вариантов особо и нет...

Ну или хитрое разделение с задачами выполняемыми в прерываниях.

 

Вообщем, для таких вещей напрашивается RTOS. Или разделение на несколько процессоров, если задача позволяет.

Изменено пользователем Diz

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообщем, для таких вещей напрашивается RTOS.

ОЗУ надо побольше, чтоб стеки таких процессов не проваливались. И тогда - хоть setjmp, хоть его обрезанные варианты-решат проблему аж бегом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще один интересный вариант реализации машины состояния на плюсах, использовали в одном проекте.

 

Каждое состояние представляется отдельным классом, унаследованным от базового. Все обработчики событий заданы в базовом классе как виртуальные функции:

virtual void eventButtonPressed() = 0 ;

virtual void eventTimerExpired() = 0 ;

 

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

 

Преимущества:

 

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

 

Можно сделать более сложную иерархию классов. Унаследовать класс от базового, определить в нем обработчик (напр. eventPacketReceived). От этого класса наследовать еще несколько подсостояний, но там этот обработчик не определять. В итоге подстостояния унаследуют реакцию на eventPacketReceived от своего суперкласса. Получается простая реализация иерархической машины состояний.

 

Можно инкапсулировать в класс данные, нужные только для конкретного состояния - например, счетчик принятых пакетов.

 

Вменяемый плюсовый компилятор делает очень хороший код с оптимизацией - на такие задачи он и рассчитан, вообщем-то.

 

Хорошие IDE умеют показывать иерархию классов, что приятно для визуализации во время кодирования.

 

 

Недостатки:

 

Много писанины, много однострочных функций. Наглядности без визуализации IDE никакой.

 

Требуется еще одна таблица или switch для выбора метода по приходу события.

 

Компилятор может оказаться невменяемым :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообщем, для таких вещей напрашивается RTOS. Или разделение на несколько процессоров, если задача позволяет.
Какой нафиг RTOS... :)

вот буквально последняя задачка, опрос 6 дискретов с тактом 50мкс с фильтрацией (это быстрый процесс)

и обмен по уарт на 230400("медленный" процесс), обмен при этом на скорости ~19Кбайт/сек

все решает точное деление на состояния автомата обмена по уарту...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какой нафиг RTOS... :)

вот буквально последняя задачка, опрос 6 дискретов с тактом 50мкс с фильтрацией (это быстрый процесс)

и обмен по уарт на 230400("медленный" процесс), обмен при этом на скорости ~19Кбайт/сек

все решает точное деление на состояния автомата обмена по уарту...

 

Ну, это деление не этапы опять же :-) Иногда хочется использовать готовую библиотеку (для того же FAT) - бить на состояния уже непросто.

Проще даже переписать с нуля.

Изменено пользователем Diz

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, это деление не этапы опять же :-) Иногда хочется использовать готовую библиотеку (для того же FAT) - бить на состояния уже непросто.

Проще даже переписать с нуля.

Да, большие готовые библиотеки лишают автоматы всяческих преимуществ...

Однако тупик с автоматами...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, большие готовые библиотеки лишают автоматы всяческих преимуществ...

Однако тупик с автоматами...

Не, не всегда так все печально...,

если есть "жирная"(библиотечная в том числе) функция,

то она работает в основном цикле проги,

автоматы просто выносятся в прерывания,

например в прерывания системного тика (10мс, 1мс, 100мкс, 25мкс...)

 

Конечно при этом нужно "вручную" рулить приоритетами и занимаемым автоматами временем,

но как бонус, 100% загрузка проца и максимальные параметры по автоматам(при удачном ручном распределении)

 

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

есть только частные ограничения реализации.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Интересно, а как сделать с набором параллельно работающих конечных автоматов (без RTOS) долго работающую задачу, требующую активного участия процессора ? Например, работу с FAT (сектор может читаться значительное время) или рендеринг экрана для UI (тоже небыстро). Разбивать на отдельные этапы некрасиво и неудобно, а иначе задача будет блокировать другие на долгое время.

.....

С FAT пример неудачен. Сектор то читается драйверком SPI, и пока он читается задача отдыхает (не требует активного участия CPU).

 

Рендеринг экрана - подходящий пример. Посмотрим по аналогии. Есть Borland'овский VCL, где вся графика обслуживается исключительно в основном потоке приложения, и при запуске какой-то длительной задачки в том же основном потоке прорисовка приложения намертво тормозится. Чтобы пользователь не подумал, что программа зависла, можно и нужно было либо стартовать доп поток, либо, что значительно проще - иногда вызвать функцию:

 

Application->ProcessMessages();

 

Вот так же можно поступить и тут. Что мешает реализовать некую функцию yield / idle - которую любой затяжной процесс сможет вызвать сам, чтобы дать поработать всем остальным процессам? Для того чтобы такую функцию можно было реализовать, необходимо чтобы был список задач(автоматов) с возможностью модификации в Run-Time (чтобы процесс вызывающий эту функцию мог быть удален из списка процессов на время своего испонения). Сосбно вот:

 

typedef void (* p_cb)(void);

#define COUNT(arr) (sizeof(arr) / sizeof((arr)[0]))

p_cb list[4];

void add_task( p_cb Callback)
{
for(int i = 0; i < COUNT(list); i++)
	if (!list[ i ])
	{
		list[ i ] = Callback;
		break;
	}
}

void idle(void)
{
for(int i = 0; i < COUNT(list); i++)
	if (list[ i ])
	{
		p_cb cb = list[ i ];
		list[ i ] = NULL;
		cb();
		list[ i ] = cb;
	}
}

void foo_1(void)
{
}

void foo_2(void)
{
}

// это долгий процесс делающий рендеринг
void foo_long(void)
{
volatile unsigned long x = -1UL;
while( x--)
{
	// ... do complex stuff

	if ( (x & 0xFF) == 0 ) // 255 iterations passed
	{
		// дадим поработать другим задачам
		idle();
	}
}
}

void main(void)
{
  add_task( foo_1 );
  add_task( foo_2 );
  add_task( foo_long );

  for(;;)
  idle();
}

 

 

Да, большие готовые библиотеки лишают автоматы всяческих преимуществ...

Однако тупик с автоматами...

Раскидать idle()'ов по ключевым точкам и автоматы получают вторую жизнь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Раскидать idle()'ов по ключевым точкам и автоматы получают вторую жизнь.

Конкретный пример. Готовая библиотека efsl. Вставка готового порта заняла час.

Как по быстрому применить автомат для разделения процессов?

Потратить несколько дней на разбиение на куски?

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

 

Тупик может не с автоматами, а в голове. Завтра выставка :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Готовая библиотека efsl.  

Как по быстрому применить автомат для разделения процессов?

Покромсать те части, которые выходят на уровень железа, Yield() вызывать оттуда . Остальное трогать не надо имхо. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...