Bonjour !
Frédéric a écrit :
> Je me suis remis à la programmation assembleur Z80 en faisant un
> reboot du jeu d'aventures que j'avais développé (et commercialisé) au
> début des années 90, sur Amstrad CPC.
Tiens ! Je serais curieux de voir ça. ;-)
> Quelqu'un aurait-il un bon tutoriel [...] sur le concept des
> coroutines ?
Je ne suis pas spécialiste, mais je me souviens avoir lu un article en
anglais sur les « protothreads », qui sont des sortes de coroutines
légères, qui n'impliquent pas des changements de contexte. Ça présentait
une implémentation en C basée uniquement sur le préprocesseur. L'idée
est d'écrire un code qui a l'air purement séquentiel, avec des appels à
YIELD(), et laisser le préprocesseur transformer ça en une machine à
états. La variable d'état correspond à la ligne où il faut reprendre
l'exécution au prochain appel. Chaque YIELD() met à jour cette variable
et fait un simple return.
De mémoire, tu écrivais un truc comme ça :
void my_coroutine(void)
{
COROUTINE_START();
foo();
YIELD();
bar();
YIELD();
baz();
COROUTINE_END();
}
et les macros le transformaient en ça :
void my_coroutine(void)
{
const int couroutine_start_line = __LINE__ + 3;
static int couroutine_next_line = couroutine_start_line;
switch (couroutine_next_line) {
case __LINE__:
foo();
couroutine_next_line = __LINE__ + 2;
return;
case __LINE__:
bar();
couroutine_next_line = __LINE__ + 2;
return;
case __LINE__:
baz();
}
couroutine_next_line = couroutine_start_line;
}
en un peu plus compliqué pour gérer des cas pathologiques.
> Du coup, je pense que la fonction 'print' se prêterait bien aux
> coroutines : à la fin de chaque caractère affiché, je rend la main à
> la boucle principale, et je continue où j'en étais à l'appel suivant.
Là, pour le coup, si tu réécris ça en machine à états à la main, je n'ai
pas l'impression que ça ajoute beaucoup de complexité. Ça revient à
transformer ça :
void print(const char *message)
{
while (*message) draw_character(*message++);
}
en ça :
/* Call with NULL to print the second and subsequent chars. */
void print(const char *message)
{
static const char *p; // state variable
if (message) p = message; // start a new message
if (*p) draw_character(*p++);
}
À+,
Edgar.