Мне нужно написать функцию с длинной логикой, которая иногда «примораживается» до следующего тика таймера. Фактически - генератор, без необходимости заботиться о локальных переменных. Через switch получается уродски.
Нашел вот такой пример https://gist.github.com/mfoliveira/957805, он хорош, но работает только с GCC. Можно ли вместо указателей на метки использовать setjmp/longjmp? Вот так:
#define yield_start() if (YIELD_ENV != NULL) longjmp(YIELD_ENV, 1);
#define yield(val) if (!setjmp(YIELD_ENV)) return val;
#define yield_end() YIELD_ENV = NULL;
В спеке сказано, что если функция, вызвавшая setjmp() завершилась, то поведение longjmp() не определено. А мне как раз надо чтобы после следующего вызова выполнение продолжилось с места yield().
Тут возможны какие-то косяки кроме потери локальных переменных (меня это устраивает)? Меня и оригинальный вариант устраивает, но интересно разобраться.
Пример текущего кода https://github.com/speedcontrols/ac_sc_grinder/blob/master/src/calibrator.h#L29-L55
Хочется развернуть так:
static jump_buf YIELD_ENV = NULL;
bool tick() {
yield_begin();
while (!wait_knob_dial.tick()) { yield(false); }
while (!calibrate_static.tick()) { yield(true); }
while (!calibrate_speed.tick()) { yield(true); }
while (!calibrate_pid.tick()) { yield(true); }
yield_end();
return false;
}
PS. Мне нужна очень простая функциональность, не надо предлагать корутины из буста и прототреды. Не хочу лишние зависимости тащить вместо десятка строк кода.