RedWing
Erfahrenes Mitglied
Hallo,
hier mal ein Beispiel wie man setjmp und longjmp benutzen kann um Koroutinen zu implementieren und dadurch Quasinebenläufigkeit von Subroutinen zu erlangen:
setjmp speichert den aktuellen Kontext in einem Buffer der vom Benutzer bereitgestellt werden muss. Nach dem Aufruf kehrt diese Funktion mit einem Wert von 0 zurück. Danach kann man eine andere Routine aufrufen. Wenn diese andere Routine dann einen korrespontiven longjmp aufruft, wird der Stack oder auch Kontext wieder hergestellt und das Programm macht da weiter wo es vorher aufgehört hat diesmal aber mit einem Rückgabewert von setjmp > 0.
longjmp restauriert den mit setjmp gesetzten Kontext und kehrt niemals zurück.
Kombiniert man diese zwei nun mit zwei oder mehreren Funktionen kann man Quasinebenläufigkeit auf Lowlevel- Basis implementieren.
Siehe auch http://en.wikipedia.org/wiki/Continuation
hier mal ein Beispiel wie man setjmp und longjmp benutzen kann um Koroutinen zu implementieren und dadurch Quasinebenläufigkeit von Subroutinen zu erlangen:
C:
#include <setjmp.h>
#include <stdio.h>
//#define DEBUG
#define SETJMP_RETVAL 1
#define LOOP_COUNTS 10
/* to make the code more readable we define the actual context
* swap with the following macro */
#ifndef DEBUG
# define SWAP_FROM_CTX_TO_CTX(from_ctx,to_ctx) \
do { \
if (!setjmp(from_ctx)) \
longjmp (to_ctx, SETJMP_RETVAL); \
} while (0)
#else
# define SWAP_FROM_CTX_TO_CTX(from_ctx,to_ctx) \
do { \
int longjmp_ret; \
if (!(longjmp_ret = setjmp (from_ctx))) \
longjmp (to_ctx, SETJMP_RETVAL); \
else \
printf ("Returning from longjmp with value %d!\n", longjmp_ret); \
} while (0)
#endif
/* thread shared variables */
jmp_buf status_ctx, heavy_computation_ctx;
int current_step;
void status_thread()
{
while (1) {
SWAP_FROM_CTX_TO_CTX(status_ctx, heavy_computation_ctx);
printf("Status: %d percent of heavy computation finished!\n",
(current_step * 100) / LOOP_COUNTS);
}
}
void heavy_computation_thread()
{
int i;
/* first time we need to start the status_thread directly */
if (!setjmp(heavy_computation_ctx))
status_thread();
#ifdef DEBUG
else
printf("Returning from first longjmp\n");
#endif
printf("Begin heavy computation!\n");
for (i = 1; i <= LOOP_COUNTS; i++) {
current_step = i;
SWAP_FROM_CTX_TO_CTX(heavy_computation_ctx, status_ctx);
printf("Continue heavy computation: step %d!\n", i);
}
printf("End heavy computation!\n");
}
int main()
{
heavy_computation_thread();
return 0;
}
setjmp speichert den aktuellen Kontext in einem Buffer der vom Benutzer bereitgestellt werden muss. Nach dem Aufruf kehrt diese Funktion mit einem Wert von 0 zurück. Danach kann man eine andere Routine aufrufen. Wenn diese andere Routine dann einen korrespontiven longjmp aufruft, wird der Stack oder auch Kontext wieder hergestellt und das Programm macht da weiter wo es vorher aufgehört hat diesmal aber mit einem Rückgabewert von setjmp > 0.
longjmp restauriert den mit setjmp gesetzten Kontext und kehrt niemals zurück.
Kombiniert man diese zwei nun mit zwei oder mehreren Funktionen kann man Quasinebenläufigkeit auf Lowlevel- Basis implementieren.
Siehe auch http://en.wikipedia.org/wiki/Continuation
Zuletzt bearbeitet: