For example:
int getNext(int n) {
while (TRUE) {
n = n+1;
yield n;
}
}
int main() {
while (TRUE) {
int n = getNext(1);
if (n > 42)
break;
printf("%d\n",n);
}
}
Such that the above code would print all numbers from 1 to 42.
I thought of making yield
change the address of getNext to the instruction after yield
. But I cant figure out how I would save the context (registers/variables) since the stack would be ran over by the caller function.
Note:
I realize that the code above can be easily implemented by static variables, but that's not the point.
In computer science, yield is an action that occurs in a computer program during multithreading, of forcing a processor to relinquish control of the current running thread, and sending it to the end of the running queue, of the same scheduling priority.
The yield keyword is use to do custom stateful iteration over a collection. The yield keyword tells the compiler that the method in which it appears is an iterator block. yield return <expression>; yield break; The yield return statement returns one element at a time.
Yield is a return measure for an investment over a set period of time, expressed as a percentage. Yield includes price increases as well as any dividends paid, calculated as the net realized return divided by the principal amount (i.e. amount invested).
You can do so, even in portable C. Here is a crude example that works (gcc -Wall gen.c
):
#include <stdbool.h>
#include <stdio.h>
#include <setjmp.h>
#define YIELD(func, n) if (! setjmp(func##_gen_jmp)) { \
func##_ret = n; \
longjmp(func##_caller_jmp, 1); \
}
#define GENERATOR(ret, func, argt, argv) \
static jmp_buf func##_caller_jmp; \
static jmp_buf func##_gen_jmp; \
static bool func##_continue=false; \
static ret func##_ret; \
\
void func##__real(argt argv); \
\
ret func(argt argv) { \
if (!func##_continue) { \
func##_continue=true ; \
if (! setjmp(func##_caller_jmp)) { \
func##__real(argv); \
} else { \
return func##_ret; \
} \
} \
else { \
longjmp(func##_gen_jmp,1); \
} \
return 0; \
} \
void func##__real(argt argv)
GENERATOR(int, getNext, int, n) {
static int counter;
counter = n;
while (true) {
counter = counter+1;
YIELD(getNext, counter);
}
}
int main() {
while (true) {
int n = getNext(1);
if (n > 42)
break;
printf("%d\n",n);
}
return 0;
}
What you're looking for is called "coroutines" and (at least not without loss of generality—see the other answer for a method for doing it in limited cases) is not possible in portable C. There are a number of tricks by which you can fake them; see http://en.wikipedia.org/wiki/Coroutine#Implementations_for_C for several.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With