Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
112
Task/Synchronous-concurrency/C/synchronous-concurrency.c
Normal file
112
Task/Synchronous-concurrency/C/synchronous-concurrency.c
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#include <stdlib.h> /* malloc(), realloc(), free() */
|
||||
#include <stdio.h> /* fopen(), fgetc(), fwrite(), printf() */
|
||||
|
||||
#include <libco.h> /* co_create(), co_switch() */
|
||||
|
||||
void
|
||||
fail(const char *message) {
|
||||
perror(message);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* These are global variables of this process. All cothreads of this
|
||||
* process will share these global variables.
|
||||
*/
|
||||
cothread_t reader;
|
||||
cothread_t printer;
|
||||
struct {
|
||||
char *buf; /* Not a C string. No terminating '\0'. */
|
||||
size_t len; /* Length of line in buffer. */
|
||||
size_t cap; /* Maximum capacity of buffer. */
|
||||
} line;
|
||||
size_t count; /* Number of lines printed. */
|
||||
|
||||
/*
|
||||
* The reader cothread reads every line of an input file, passes each
|
||||
* line to the printer cothread, and reports the number of lines.
|
||||
*/
|
||||
void
|
||||
reader_entry(void)
|
||||
{
|
||||
FILE *input;
|
||||
size_t newcap;
|
||||
int c, eof, eol;
|
||||
char *newbuf;
|
||||
|
||||
input = fopen("input.txt", "r");
|
||||
if (input == NULL)
|
||||
fail("fopen");
|
||||
|
||||
line.buf = malloc(line.cap = 4096); /* New buffer. */
|
||||
if (line.buf == NULL)
|
||||
fail("malloc");
|
||||
line.len = 0; /* Start with an empty line. */
|
||||
|
||||
do {
|
||||
c = fgetc(input); /* Read next character. */
|
||||
if (ferror(input))
|
||||
fail("fgetc");
|
||||
|
||||
eof = (c == EOF);
|
||||
if (eof) {
|
||||
/*
|
||||
* End of file is also end of line,
|
||||
` * unless the line would be empty.
|
||||
*/
|
||||
eol = (line.len > 0);
|
||||
} else {
|
||||
/* Append c to the buffer. */
|
||||
if (line.len == line.cap) {
|
||||
/* Need a bigger buffer! */
|
||||
newcap = line.cap * 2;
|
||||
newbuf = realloc(line.buf, newcap);
|
||||
if (newbuf == NULL)
|
||||
fail("realloc");
|
||||
line.buf = newbuf;
|
||||
line.cap = newcap;
|
||||
}
|
||||
line.buf[line.len++] = c;
|
||||
|
||||
/* '\n' is end of line. */
|
||||
eol = (c == '\n');
|
||||
}
|
||||
|
||||
if (eol) {
|
||||
/* Pass our complete line to the printer. */
|
||||
co_switch(printer);
|
||||
line.len = 0; /* Destroy our line. */
|
||||
}
|
||||
} while (!eof);
|
||||
|
||||
free(line.buf);
|
||||
line.buf = NULL; /* Stops a loop in the printer. */
|
||||
|
||||
printf("Printed %zu lines.\n", count);
|
||||
co_switch(printer);
|
||||
}
|
||||
|
||||
/*
|
||||
* The printer cothread starts the reader cothread, prints every line
|
||||
* line from the reader cothread, and counts the number of lines.
|
||||
*/
|
||||
int
|
||||
main()
|
||||
{
|
||||
reader = co_create(4096, reader_entry);
|
||||
printer = co_active();
|
||||
count = 0;
|
||||
|
||||
for (;;) {
|
||||
co_switch(reader);
|
||||
if (line.buf == NULL)
|
||||
break;
|
||||
|
||||
/* Print this line. Count it. */
|
||||
fwrite(line.buf, 1, line.len, stdout);
|
||||
count++;
|
||||
}
|
||||
|
||||
co_delete(reader);
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue