Здравствуйте, Videoman, Вы писали:
V>Как такое можно организовать проще всего? Обязательно нужно кроссплатформенное решение, без погружения в дебри с ассемблером, регистрами и т.л.
Обычный switch
V>Большая просьба по возможности воздержаться от тыканья в готовые библиотеки, в плане бери вот это, там всё уже есть и не думай. Хочется понять основные идеи и подходы, а не максимально быстро начать писать код в продакшене.
int fn_setup(context *ctx,int event_code);
int fn_loop(context *ctx) {
switch(ctx->line) { default:
case 0: /* code 1 */ ctx->line=1; return 1;
case 1: /* code 2 формируем запрос */ ctx->line=2; return 2; // предываемся и просми обработать запрос rc=2 (hint)
case 2: /* code 3 анализируем ответ и был ли он вообще обработан */ ctx->line=3; return 1;
case 3: /* code 4 */ ctx->line=4; return 1;
/*...*/
}
return 0;
}
Функция которая имеет состояние и выполняется постепенно. "Квант исполнения" передаётся через метод loop. Управляющие воздействия через метод setup.
Если метод loop возвращает 0 значит функция отработала, не 0 значит еще требуются итерации. setup также 0-ок, не 0 значит что-то иное.
Для управления ресерсами можно использовать setup
setup(ctx,event_Init) -- подготаливаем функцию к работе и устанавливаем ctx->line=0
while( loop(ctx) ) {} -- проводим выполнение
setup(ctx,event_Done) -- освобождаем ресурсы
Обработку сетевых запросов, дочерних асинхронных функций, ожиданий и других прерываний обрабатывает планировщик (scheduler). В задачи которого так же входит убить все дочерние функции если их родительская померла. Это что бы структурированность была.
Дальше это всё ныкается в макросы с использованием __COUNTER__ или __LINE__ если __COUNTER__ не поддерживается.
| | типа такого loop-fn.h |
| | /* loop-fn.h - sequential execution function */
#ifndef __LOOP_FN_H__
#define __LOOP_FN_H__
typedef int loop_t;
#define LOOP_RESET(loop) { loop=0; }
#if defined(__COUNTER__) && __COUNTER__!=__COUNTER__
#define LOOP_BEGIN(loop) { enum { __loop_base=__COUNTER__ }; \
loop_t *__loop=&(loop); __loop_switch: int __loop_rv=1; \
switch(*__loop) { default: *__loop=0; case 0: {
#define LOOP_POINT { enum { __loop_case=__COUNTER__-__loop_base }; \
*__loop=__loop_case; goto __loop_leave; case __loop_case:{} }
#else
#define LOOP_BEGIN(loop) {loop_t*__loop=&(loop);__loop_switch:int __loop_rv=1;\
switch(*__loop){ default: case 0: *__loop=__LINE__; case __LINE__:{
#define LOOP_POINT { *__loop=__LINE__; goto __loop_leave; case __LINE__:{} }
#endif
#define LOOP_END { __loop_end: *__loop=-1; case -1: return 0; \
{ goto __loop_end; goto __loop_switch; /* make msvc happy */ } } \
}} __loop_leave: return __loop_rv; }
#define LOOP_SET_RV(rv) { __loop_rv=(rv); } /* rv must be non zero */
#define LOOP_INT(n) { __loop_rv=(n); LOOP_POINT } /* interrupt n */
/* for manual labeling: enum { L01=1,L02,L03,L04 }; ... LOOP_POINT_(L02) */
#define LOOP_POINT_(name) { *__loop=name; goto __loop_leave; case name:{} }
#define LOOP_INT_(n,name) { __loop_rv=(n); LOOP_POINT_(name) }
#endif /* __LOOP_FN_H__ */
|
| | |
Из минусов надо помнить вы во switch и есть ограничения на вложенный switch, все временные переменные и структуры которые должны жить между преключениями надо объявлять явнов контексте функции. (Зато можно сохранять состояние на диск или передавать посети и возобновлять исполнение на другой машине да и работает на любой версии обычного C).
V>Если читаемый подход возможен только в С++20, то придется конечно дрейфовать туда, ничего не поделаешь.