Сообщение Re[17]: Вопрос по корутинам от 28.08.2025 10:08
Изменено 28.08.2025 10:10 rg45
Re[17]: Вопрос по корутинам
Здравствуйте, kov_serg, Вы писали:
_>https://coliru.stacked-crooked.com/a/86f2c863b4d93396
_>
И что, тебе реально твой вариант больше нравится? Лично я бы не выбрал этот вариант из-за одних только "вспомогательных макросов". Ну и вообще...
_>https://coliru.stacked-crooked.com/a/86f2c863b4d93396
_>
int fn1_loop(fn1_t *my) {
_> LOOP_BEGIN(my->loop)
my->>value="Idle"; LOOP_POINT
my->>value="Started"; LOOP_POINT
my->>value="Processing"; LOOP_POINT
_> while (*my->param < 10 + my->machineID) {
my->>value="Waiting"; LOOP_POINT
_> }
my->>value="Stopped";
_> LOOP_END
_>}
[cut]typedef int loop_t;
Жульничаешь? Изюм выковыриваешь? Ну, я помогу тебе сделать этот нелёгкий шаг. Сравни следующие два варианта:
С корутинами:
[cpp]
#include <generator>
#include <iostream>
#include <string>
#include <ranges>
#include <vector>
std::generator<std::string> runMachine(const int& param) {
co_yield "Idle";
co_yield "Started";
co_yield "Processing";
while (param < 10)
{
co_yield "Waiting";
}
co_yield "Stopped";
}
std::generator<std::generator<std::string>> createMachines(const int& param, size_t n) {
for (size_t i = 0; i < n; ++i)
co_yield runMachine(param);
}
int main() {
int param = 0;
std::vector machines(std::from_range, createMachines(param, 333));
for(bool active = true; active;) {
active = false;
for (size_t i = 0; i < machines.size(); ++i) {
if (machines[i].begin() != machines[i].end()) {
std::cout << "Machine " << i + 1 << ": " << *machines[i].begin() << std::endl;
active = true;
}
}
++param;
}
}
[/cpp]
На С со "вспомогательными макросами":
[c]
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; } } }} __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) }
//------------------------------------------------------------------------------
enum { sevInit, sevDone };
typedef int (*afn_loop_fn)(void *ctx);
typedef int (*afn_setup_fn)(void *ctx,int sev);
typedef struct {
void *ctx;
int (*loop)(void *ctx);
int (*setup)(void *ctx,int sev);
} afn_t;
//------------------------------------------------------------------------------
typedef struct {
loop_t loop;
int machineID, *param;
const char* value;
} fn1_t;
int fn1_setup(fn1_t* my,int sev) {
switch(sev) {
case sevInit: {
LOOP_RESET(my->loop);
my->value="initialized";
} break;
case sevDone: {
my->loop=-1;
} break;
}
return 0;
}
int fn1_loop(fn1_t *my) {
LOOP_BEGIN(my->loop)
my->value="Idle"; LOOP_POINT
my->value="Started"; LOOP_POINT
my->value="Processing"; LOOP_POINT
while (*my->param < 10 + my->machineID) {
my->value="Waiting"; LOOP_POINT
}
my->value="Stopped";
LOOP_END
}
//------------------------------------------------------------------------------
typedef void (*cycle_fn)(void *ctx);
typedef struct {
afn_t *group; int current,count;
void (*cycle)(void *ctx); void *cycle_ctx;
} fn2_t;
int fn2_setup(fn2_t* my, int sev) {
int i,err=0;
for(i=0;i<my->count;i++) {
afn_t *fn=&my->group[i];
if (fn->setup(fn->ctx,sev)) err++;
}
my->current=0;
return err;
}
int fn2_loop(fn2_t* my) {
if (my->count>0) {
afn_t *fn=&my->group[my->current];
if (fn->loop(fn->ctx)) my->current++; else {
my->group[my->current]=my->group[--my->count];
}
}
if (my->current>=my->count) { my->current=0;
if (my->cycle) my->cycle(my->cycle_ctx);
}
return my->count>0 ? 1 : 0;
}
//------------------------------------------------------------------------------
#include <stdio.h>
typedef struct { fn1_t *list; int count, param; } show_ctx_t;
void show(show_ctx_t* my) {
int i,n;
n=my->count;
for(i=0;i<n;i++) {
fn1_t *f=&my->list[i];
printf("| ");
printf("Machine %d: %10s ",f->machineID, f->value);
}
printf("|\n");
my->param++;
}
int main() {
enum { N=5 };
fn1_t fn[N]; afn_t afn[N];
show_ctx_t show_ctx[1];
fn2_t fn2[1];
int i;
for(i=0;i<N;i++) {
fn[i].machineID=i+1;
fn[i].param=&show_ctx->param;
}
show_ctx->param=0;
show_ctx->list=fn;
show_ctx->count=N;
fn2->cycle=(cycle_fn)show;
fn2->cycle_ctx=show_ctx;
for(i=0;i<N;i++) {
afn[i].ctx=&fn[i];
afn[i].setup=(afn_setup_fn)fn1_setup;
afn[i].loop=(afn_loop_fn)fn1_loop;
}
fn2->group=afn;
fn2->count=N;
fn2_setup(fn2,sevInit);
while(fn2_loop(fn2)) {}
fn2_setup(fn2,sevDone);
return 0;
}
И что, тебе реально твой вариант больше нравится? Лично я бы не выбрал этот вариант из-за одних только "вспомогательных макросов". Ну и вообще...
Re[17]: Вопрос по корутинам
Здравствуйте, kov_serg, Вы писали:
_>https://coliru.stacked-crooked.com/a/86f2c863b4d93396
_>
Жульничаешь? Изюм выковыриваешь? Ну, я помогу тебе сделать этот нелёгкий шаг. Сравни следующие два варианта:
С корутинами:
На С со "вспомогательными макросами":
И что, тебе реально твой вариант больше нравится? Лично я бы не выбрал этот вариант из-за одних только "вспомогательных макросов". Ну и вообще...
_>https://coliru.stacked-crooked.com/a/86f2c863b4d93396
_>
int fn1_loop(fn1_t *my) {
_> LOOP_BEGIN(my->loop)
my->>value="Idle"; LOOP_POINT
my->>value="Started"; LOOP_POINT
my->>value="Processing"; LOOP_POINT
_> while (*my->param < 10 + my->machineID) {
my->>value="Waiting"; LOOP_POINT
_> }
my->>value="Stopped";
_> LOOP_END
_>}
Жульничаешь? Изюм выковыриваешь? Ну, я помогу тебе сделать этот нелёгкий шаг. Сравни следующие два варианта:
С корутинами:
#include <generator>
#include <iostream>
#include <string>
#include <ranges>
#include <vector>
std::generator<std::string> runMachine(const int& param) {
co_yield "Idle";
co_yield "Started";
co_yield "Processing";
while (param < 10)
{
co_yield "Waiting";
}
co_yield "Stopped";
}
std::generator<std::generator<std::string>> createMachines(const int& param, size_t n) {
for (size_t i = 0; i < n; ++i)
co_yield runMachine(param);
}
int main() {
int param = 0;
std::vector machines(std::from_range, createMachines(param, 333));
for(bool active = true; active;) {
active = false;
for (size_t i = 0; i < machines.size(); ++i) {
if (machines[i].begin() != machines[i].end()) {
std::cout << "Machine " << i + 1 << ": " << *machines[i].begin() << std::endl;
active = true;
}
}
++param;
}
}
На С со "вспомогательными макросами":
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; } } \
}} __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) }
//------------------------------------------------------------------------------
enum { sevInit, sevDone };
typedef int (*afn_loop_fn)(void *ctx);
typedef int (*afn_setup_fn)(void *ctx,int sev);
typedef struct {
void *ctx;
int (*loop)(void *ctx);
int (*setup)(void *ctx,int sev);
} afn_t;
//------------------------------------------------------------------------------
typedef struct {
loop_t loop;
int machineID, *param;
const char* value;
} fn1_t;
int fn1_setup(fn1_t* my,int sev) {
switch(sev) {
case sevInit: {
LOOP_RESET(my->loop);
my->value="initialized";
} break;
case sevDone: {
my->loop=-1;
} break;
}
return 0;
}
int fn1_loop(fn1_t *my) {
LOOP_BEGIN(my->loop)
my->value="Idle"; LOOP_POINT
my->value="Started"; LOOP_POINT
my->value="Processing"; LOOP_POINT
while (*my->param < 10 + my->machineID) {
my->value="Waiting"; LOOP_POINT
}
my->value="Stopped";
LOOP_END
}
//------------------------------------------------------------------------------
typedef void (*cycle_fn)(void *ctx);
typedef struct {
afn_t *group; int current,count;
void (*cycle)(void *ctx); void *cycle_ctx;
} fn2_t;
int fn2_setup(fn2_t* my, int sev) {
int i,err=0;
for(i=0;i<my->count;i++) {
afn_t *fn=&my->group[i];
if (fn->setup(fn->ctx,sev)) err++;
}
my->current=0;
return err;
}
int fn2_loop(fn2_t* my) {
if (my->count>0) {
afn_t *fn=&my->group[my->current];
if (fn->loop(fn->ctx)) my->current++; else {
my->group[my->current]=my->group[--my->count];
}
}
if (my->current>=my->count) { my->current=0;
if (my->cycle) my->cycle(my->cycle_ctx);
}
return my->count>0 ? 1 : 0;
}
//------------------------------------------------------------------------------
#include <stdio.h>
typedef struct { fn1_t *list; int count, param; } show_ctx_t;
void show(show_ctx_t* my) {
int i,n;
n=my->count;
for(i=0;i<n;i++) {
fn1_t *f=&my->list[i];
printf("| ");
printf("Machine %d: %10s ",f->machineID, f->value);
}
printf("|\n");
my->param++;
}
int main() {
enum { N=5 };
fn1_t fn[N]; afn_t afn[N];
show_ctx_t show_ctx[1];
fn2_t fn2[1];
int i;
for(i=0;i<N;i++) {
fn[i].machineID=i+1;
fn[i].param=&show_ctx->param;
}
show_ctx->param=0;
show_ctx->list=fn;
show_ctx->count=N;
fn2->cycle=(cycle_fn)show;
fn2->cycle_ctx=show_ctx;
for(i=0;i<N;i++) {
afn[i].ctx=&fn[i];
afn[i].setup=(afn_setup_fn)fn1_setup;
afn[i].loop=(afn_loop_fn)fn1_loop;
}
fn2->group=afn;
fn2->count=N;
fn2_setup(fn2,sevInit);
while(fn2_loop(fn2)) {}
fn2_setup(fn2,sevDone);
return 0;
}
И что, тебе реально твой вариант больше нравится? Лично я бы не выбрал этот вариант из-за одних только "вспомогательных макросов". Ну и вообще...