Corrutinas en C/C++

Las corrutinas son estructuras de control general en las que el control de flujo se pasa de forma cooperativa entre dos rutinas diferentes sin retorno. 
Si ha usado Python o C#, es posible que sepa que hay una palabra clave llamada yield que permite un ciclo de ida y vuelta entre la persona que llama y la función llamada hasta que la persona que llama no termina con la función o la función termina debido a alguna lógica. es dado.

Ejemplo de código Python3 de rendimiento. 

Python

# Python program to generate numbers in a
# range using yield
  
def rangeN(a, b):
    i = a
    while (i < b):
        yield i
        i += 1  # Next execution resumes
                # from this point   
 
for i in rangeN(1, 5):
        print(i)
Producción

1
2
3
4

Este código demuestra cómo funciona el rendimiento y da una breve idea de cómo se cambia el control entre la persona que llama y la persona que llama. 

¿Por qué se necesitan rutinas? 

Para leer un archivo y analizarlo mientras lee algunos datos significativos, puede leer paso a paso en cada línea, lo cual está bien. También puede cargar todo el contenido en la memoria, lo que no se recomienda para casos de texto grandes, por ejemplo, editores de texto como Microsoft Word o en sistemas modernos que solo usan Pipes. 

En El arte de la programación informática, Donald Knuth presenta una solución a este tipo de problema. Su respuesta es descartar por completo el concepto de pila. Deje de pensar en un proceso como el que llama y el otro como el que recibe la llamada, y empiece a pensar en ellos como iguales cooperantes. Así que ahora podemos intentar y ver cómo lograr lo mismo en C.  

function read():
   /* reads the content in the desired number 
      of steps and returns back control to parser
      but saves its own state of function. */

function parse():
   a = read()
   while (a)
   {
       // do something
       a = read()
   }

Bien, en la práctica esta estructura se ve muy similar a la estructura llamador-llamado de C. Pero lo que requerimos aquí es que el lector debe recordar su estado. Debe recordar dónde estuvo la última vez que hizo el trabajo y también debe poder restablecerse.

¿Cómo implementar Coroutines en C? 

El desafío es tener rutinas en lenguaje C, que es en sí mismo un lenguaje basado en pilas, es decir, en cada respuesta a una llamada de función en lenguaje C, se inicializa una pila que realiza un seguimiento de todas sus variables y constantes y se destruye cuando la llamada de función termina
 

C

int read(void)
{
    int i;
    for (i = 0; i < 10; i++)
        return i; /* Well on the first run itself
                    the function will be destroyed */
}

Tenemos que hacer dos cosas:  

  1. Reanudar el control a su último estado
  2. Hacer que los datos persistan a través de llamadas

Ambos problemas anteriores deben resolverse mediante el uso de variables estáticas. Pero, ¿cómo recordar el estado y también volver al mismo estado de ejecución que antes, es decir, las líneas de código después del retorno o el bucle? Podemos usar sentencias GOTO. Lo cual no se recomienda en general. Aquí, podemos probar algo llamado dispositivo de Duff . Así que finalmente pasamos al código de solución.

C++

// C++ program to demonstrate how coroutines
// can be implemented in C++.
#include <iostream>
using namespace std;
 
int range(int a, int b)
{
    static long long int i;
    static int state = 0;
    switch (state) {
    case 0: /* start of function */
        state = 1;
        for (i = a; i < b; i++) {
            return i;
 
        /* Returns control */
        case 1:
            cout << "control at range"
                 << endl; /* resume control straight
                           after the return */
        }
    }
    state = 0;
    return 0;
}
 
// Driver code
int main()
{
    int i; // For really large numbers
 
    for (; i = range(1, 5);)
        cout << "control at main :" << i << endl;
 
    return 0;
}

C

// C program to demonstrate how coroutines
// can be implemented in C.
#include<stdio.h>
 
int range(int a, int b)
{
    static long long int i;
    static int state = 0;
    switch (state)
    {
    case 0: /* start of function */
        state = 1;
        for (i = a; i < b; i++)
        {
            return i;
 
        /* Returns control */
        case 1:; /* resume control straight
                    after the return */
        }
    }
    state = 0;
    return 0;
}
 
// Driver code
int main()
{
    int i; //For really large numbers
 
    for (; i=range(1, 5);)
        printf("control at main :%d\n", i);
 
    return 0;
}
Producción

control at main :1
control at range
control at main :2
control at range
control at main :3
control at range
control at main :4
control at range

La solución utiliza nuestra comprensión del dispositivo de Duff y hace que juegue con él. Básicamente, ahora podemos tener varias declaraciones de retorno dentro del bucle for y cada vez que regresamos a un estado de ejecución diferente si está programado para hacerlo. Esta implementación solo imita la función de rango de python , que también se basa en coroutine, ya que devuelve objetos generadores a partir de Python3.

Fuente:  Coroutines en C por Simon Tatham

Este artículo es una contribución de Rajat Kanti Bhattacharjee . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente. 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *