Re: Асинхронщина
От: kov_serg Россия  
Дата: 06.12.25 09:31
Оценка: 4 (1)
Здравствуйте, 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, то придется конечно дрейфовать туда, ничего не поделаешь.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.