Редактировать: Это ставится на голосование, поэтому я хотел бы добавить разъяснение для потомков. Это не очень хороший способ решить эту проблему - вы бы никогда не захотели сделать это вручную. Совместные пользовательские потоки хороши и могут быть использованы для реализации умных вещей, таких как сопрограммы, но если вы хотите сделать это, вам следует использовать библиотеку типа libcoroutine , которая обрабатывает кусочки волосков для вас. Однако, хотя это и не практичное решение, оно все же представляет интересную идею и является интересным примером планирования и ограничений чистого C99.
Это плохой ответ. Однако он не зависит от платформы и, кроме того, использует только функции, определенные в стандарте C99.
С другой стороны, он загружает процессор (в C99 нет функций sleep
, поэтому нам приходится ждать-занят), использует то, что я могу назвать только магией, чтобы зарезервировать место в стеке и полностью злоупотребляет setjmp
. Он даже использует глобальные переменные! И все же, это работает.
Техника называется взаимодействующими пользовательскими потоками, также называемыми волокнами. Я реализовал это, как я уже говорил, используя setjmp
и longjmp
. context_switch
выполняет простое планирование Round Robin.
Это код:
#include <stdio.h>
#include <setjmp.h>
#include <time.h>
static jmp_buf jmp[2];
static int cur;
void context_switch()
{
/* sleep(1) */ /* C99 doesn't have any sleeping functions */
if (!setjmp(jmp[cur])) {
if ((sizeof(jmp)/sizeof(*jmp)) == ++cur)
cur = 0;
longjmp(jmp[cur], 1);
}
}
void fun2()
{
char cushion[1000]; /* reserve some stack space */
time_t old_time, new_time;
cushion[0] = '@'; /* don't optimize my cushion away */
old_time = time(NULL);
cur = 1; /* the first thread to context switch is this one */
setjmp(jmp[1]);
while (1) {
context_switch();
new_time = time(NULL);
if ((new_time - old_time) > (2 * 60)) {
old_time = new_time;
printf("Printed every 2 minutes\n");
}
}
}
void fun1()
{
char cushion[1000]; /* reserve some stack space */
time_t old_time, new_time;
cushion[0] = '@'; /* don't optimize my cushion away */
if (!setjmp(jmp[0]))
fun2();
old_time = time(NULL);
while (1) {
context_switch();
new_time = time(NULL);
if ((new_time - old_time) > (1 * 60)) {
old_time = new_time;
printf("Printed every 1 minute\n");
}
}
}
int main(int argc, char **argv)
{
fun1();
return 0;
}
И вот что я получаю:
$ gcc -ggdb -std=c99 -o silly silly_setjmp.c
$ ./silly
Printed every 1 minute
Printed every 2 minutes
Printed every 1 minute
Printed every 1 minute
...