Как реализовать сопрограмму в течение цикла в C - PullRequest
0 голосов
/ 23 мая 2018

Вот код детали:

void a()
{
    printf("entering a\n");
    int i;
    for(i = 0; i < 3; i++){
        if(setjmp(a_buf) == 0) {
            printf("A step %d\n", i);
            b();
        } else {
            longjmp(b_buf, 1);
        }
    }
    printf("returning from a\n");
}

void b()
{
    printf("entering b\n");
    int i;
    for(i = 0; i < 5; i++){
        if(setjmp(b_buf) == 0) {
            printf("B step %d\n", i);
            a();
        } else {
            longjmp(a_buf, 1);
        }
    }
    printf("returning from b\n");
}

У меня есть два процесса a & b.Как заставить их работать как сопрограмма.Пожелайте им сделать A Step 0, затем B Step 0, затем вернуться к A Step 1 ... пока оба не закончат.Но похоже, что счетчик i никогда не менялся.

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

То, что вы пытаетесь достичь с помощью своего кода, здесь не определено.

Цитирование C11, глава §7.13.2.1p2

Функция longjmp восстанавливает среду, сохраненную при последнем вызове setjmp макрос в том же вызове программы с соответствующим аргументом jmp_buf.Если такого вызова не было, или если вызов был из другого потока выполнения, или если функция, содержащая вызов макроса setjmp, прекратила выполнение в промежуточный период, или если вызовмакрос setjmp находился в области действия идентификатора с изменяемым типом, и выполнение оставило эту область в промежуточном состоянии, поведение не определено.

Выделение шахты

Относительно того, что считается завершенным исполнением:

Цитирование C11, глава §note248

Например, путем выполнения оператора возврата или потому чтодругой вызов longjmp вызвал переход к вызову setjmp в функции ранее в наборе вложенных вызовов.

Итак, сначала вы вызываете a(), и он вызывает b() после установки a_buf.Теперь b() устанавливает b_buf и возвращается к a.На этом этапе выполнение b было прекращено, и если вы вернетесь к b_buf, поведение будет неопределенным.

Одним из возможных решений вашей проблемы может быть определение функций a_step() и b_step(), которые выполняют только один шаг a() и b() соответственно.Затем назовите их альтернативно в цикле.

0 голосов
/ 23 мая 2018

Функции setjmp() и longjmp() могут использоваться только для выхода из вложенной подпрограммы, как своего рода «throw / catch».Их нельзя использовать для повторного входа в подпрограмму, которая уже вышла, либо через return, либо через longjmp().Короче говоря, их нельзя использовать таким образом.

Единственный четко определенный способ реализации сопрограмм в C - это как конечный автомат .Невозможно реализовать сопрограммы как обычные подпрограммы, поскольку это несовместимо со стеком C.

...