Generator/Exponential: Difference between revisions

→‎{{libheader|libco}}: Add some ugly code to check for memory allocation, and to free memory. C is being an awful language.
(→‎{{header|E}}: Add C using libco.)
(→‎{{libheader|libco}}: Add some ugly code to check for memory allocation, and to free memory. C is being an awful language.)
Line 22:
 
<lang c>#include <inttypes.h> /* int64_t, PRId64 */
#include <stdlib.h> /* exit() */
#include <stdio.h> /* printf() */
 
#include <libco.h> /* co_active()co_{active, co_create()create, co_switchdelete,switch}() */
 
 
Line 30 ⟶ 31:
/* A generator that yields values of type int64_t. */
struct gen64 {
cothread_t giver; /* this coroutinecothread calls yield64() */
cothread_t taker; /* this coroutinecothread calls next64() */
int64_t given;
void (*free)(struct gen64 *);
void *garbage;
};
 
Line 50 ⟶ 53:
co_switch(gen->giver);
return gen->given;
}
 
static void
gen64_free(struct gen64 *gen)
{
co_delete(gen->giver);
}
 
Line 55 ⟶ 64:
 
/*
* Creates a coroutinecothread for the generator. The first call to next64(gen)
* will enter the coroutinecothread; the entry function must copy the pointer
* from the global variable struct gen64 *entry64.
/*
* Use gen->free(gen) to free the cothread.
*/
inline void
gen64_init(struct gen64 *gen, void (*entry)(void))
{
if ((gen->giver = co_create(4096, entry);) == NULL) {
/* Perhaps malloc() failed */
fputs("co_create: Cannot create cothread\n", stderr);
exit(1);
}
gen->free = gen64_free;
entry64 = gen;
}
 
 
 
/* Defines a static entry function for a coroutine. */
#define ENTRY(name, code) static void name(void) { code; }
 
/*
Line 96 ⟶ 109:
}
 
/* stuff for squares_without_cubes() */
#define ENTRY(name, code) static void name(void) { code; }
ENTRY(enter_squares, powers(entry64, 2))
ENTRY(enter_cubes, powers(entry64, 3))
 
struct swc {
struct gen64 cubes;
struct gen64 squares;
void (*old_free)(struct gen64 *);
};
 
static void
swc_free(struct gen64 *gen)
{
struct swc *f = gen->garbage;
f->cubes.free(&f->cubes);
f->squares.free(&f->squares);
f->old_free(gen);
}
 
/*
Line 106 ⟶ 136:
squares_without_cubes(struct gen64 *gen)
{
struct gen64swc cubes, squaresf;
int64_t c, s;
 
gen64_init(&f.cubes, enter_cubes);
c = next64(&f.cubes);
 
gen64_init(&f.squares, enter_squares);
s = next64(&f.squares);
 
/* Allow other cothread to free this generator. */
gen64_init(&squares, enter_squares);
f.old_free = gen->free;
s = next64(&squares);
gen->garbage = &f;
gen->free = swc_free;
 
for (;;) {
Line 119 ⟶ 154:
yield64(gen, s);
while (c <= s)
c = next64(&f.cubes);
s = next64(&f.squares);
}
/* NOTREACHED */
Line 145 ⟶ 180:
printf("%" PRId64 "\n", next64(&gen));
 
gen.free(&gen); /* Free memory. */
/*
* This program has no way to free the memory for all three
* coroutines. It can do co_delete(gen.giver) but then there
* would be no way to free the other two coroutines for squares
* and cubes.
*
* Here the program exits, to free the memory for the entire
* program.
*/
return 0;
}</lang>
Anonymous user