Cuando se ejecuta un programa python, tiene esencialmente dos piezas de código que se ejecutan bajo el capó.
En primer lugar, el código C del intérprete CPython se ejecuta y utiliza la pila C estándar para guardar sus estructuras internas de pila. En segundo lugar, el código de bytes interpretado por python real que no utiliza la pila C, sino que utiliza el montón para guardar sus marcos de pila. Un greenlet es solo un código python estándar y, por lo tanto, se comporta de forma idéntica.
Ahora en una aplicación microteñida típica, tendría miles o incluso millones de microthreads (greenlets) cambiando por todos lados. Cada interruptor es esencialmente equivalente a una llamada a función con un retorno diferido (por así decirlo) y por lo tanto usará un poco de pila. El problema es que la pila C del intérprete tarde o temprano golpeará un desbordamiento de la pila. Esto es exactamente a lo que apunta la extensión de greenlet, está diseñado para mover piezas de la pila hacia y desde el montón para evitar este problema.
Como saben, hay tres acontecimientos fundamentales con Verdecillo, un engendro, un interruptor y un retorno, por lo que vamos a ver los que a su vez:
A) Una freza
El recientemente greenlet generado se asocia con su propia dirección base en la pila (donde estamos actualmente). Aparte de eso, no sucede nada especial. El código python del greenlet recién generado usa el montón de una manera normal y el intérprete continúa usando el C-stack como de costumbre.
B) Un interruptor de
Cuando un greenlet se conmuta a partir de una greenlet de conmutación, la parte correspondiente de la C-pila (empezando por la dirección base de la greenlet switchng) se copia en el montón. El área copiada de C-stack se libera y el intérprete de Greenlet conmutado previamente guardado datos de pila se copia del montón al área C-stack recién liberada. El código python del greenlet conmutado continúa usando el montón de una manera normal. Por supuesto, el código de extensión realiza un seguimiento de todo esto (qué sección de pila va a qué punto de referencia, etc.).
C) A Return
La pila está intacto y el área montón de la greenlet volver es liberado por el recolector de pitón de basura.
Básicamente esto es todo, muchos más detalles y explicaciones se pueden encontrar en (http://www.stackless.com/pipermail/stackless-dev/2004-March/000022.html) o simplemente leyendo el código como se indica en la respuesta de Alex.
Ese bloque de comentarios me resulta confuso y realmente no responde mis preguntas. Solo esperaba un resumen/respuesta conciso y de alto nivel. Gracias por los punteros de todos modos, espero que sean útiles para otros (o para mí mismo cuando encuentre más tiempo para el buceo de origen). – Yang
@Yang, esas 86 líneas ** son ** un resumen conciso y de alto nivel, alcanzando la mayoría de los aspectos más destacados de las 1410 líneas de código que juntas forman los archivos '.c' y' .h'! "Memcpy guarda las porciones de apilamiento en la memoria asignada y reasignada por el administrador de memoria de Python y restaurada por memcpy nuevamente en la pila (luego se libera la memoria de Python)" es aún más conciso y de nivel superior (pero ya lo dije todo) esto en mi respuesta!) pero obviamente falta algunos detalles importantes (ya que son dos líneas de texto, no 86 ;-). ¿Qué texto mágico esperas que se interponga y te haga feliz? –
Para empezar: ¿qué es "datos de pila de Greenlet"? ¿Es solo la contabilidad para el greenlet? ¿O incluye realmente ciertos marcos de C stack? ¿Cuál es el "lugar correcto en la pila" de un punto verde? ¿Por qué siempre hay dos bloques de Greenlet/por qué el anterior está en montón? ¿Qué son los "datos no relacionados con este punto verde" debajo de los "datos de la pila de Greenlet"? Diff btwn "datos no relacionados" y "datos más nuevos"? Etc. Es una pequeña cantidad de C, pero también estoy ocupado y esto no está relacionado en absoluto con mi trabajo actual, solo por curiosidad. La pregunta simplemente estalló en mi cabeza. De nuevo, feliz de bucear más tarde una vez que encuentre el tiempo. – Yang