Что будет, если не назвать урожай в клетчатке?

Как я понял из документации yield() функция передает управление другому волокну. Что произойдет, если мы не будем называть yield в волокне в D? Это будет означать, что нить будет зависать?

Или я неправильно понимаю, что волокна работают внутри потоков и они работают внутри процесса? И процесс может иметь или threads или же fibers?

2 ответа

Решение

Чтобы ответить на этот вопрос, важно понять, как работают волокна. Когда вы звоните Fiber.call() метод, текущий контекст выполнения (состояние регистра ЦП) выгружается в память и вместо этого загружается контекст выполнения для этого объекта волокна. Когда вы звоните Fiber.yield() текущий контекст выполнения также сбрасывается, но управление передается тому, кто в последний раз вызывал текущее волокно. Это может быть как другой контекст волокна, так и контекст простого потока - он не должен знать, так как любой контекст выполнения полностью определяется дампированными данными, ему даже не нужно знать о волокне.

Когда функция волокна заканчивается, она просто возвращает управление последнему вызывающему абоненту, как если бы yield позвони в самый конец. Основное отличие состоит в том, что, когда функция волокна заканчивается, соответствующий объект волокна переходит в состояние "прекращено" и при выходе из него всегда остается в состоянии "работа" (даже если технически больше нет необходимости). Это важно, потому что это только определенное поведение для сброса и повторного использования волокон в завершенном состоянии.

Распространенная ошибка - рассматривать волокна как своего рода задачи и ожидать семантики планирования. Дело не в том, что волокно само по себе является простым примитивом переключения контекста для реализации любой интеллектуальной системы задач на вершине, никогда не будет никакого планирования самостоятельно.

Пример кода, показывающий соответствующую семантику:

void main ( )
{
    import core.thread, std.stdio;

    Fiber fiber1, fiber2;

    fiber1 = new Fiber({        
        fiber2.call();
        Fiber.yield(); 
    });

    fiber2 = new Fiber({
        Fiber.yield(); 
    });

    fiber1.call(); // switches to fiber1, which switches to fiber2
                   // which yield back to fiber1 and finally fiber1 yield back to main
    assert (fiber1.state == Fiber.State.HOLD && fiber2.state == Fiber.State.HOLD);
    fiber2.call(); // switches to fiber2 which reaches end of function
                   // and switches back to main upon exit
    assert (fiber1.state == Fiber.State.HOLD && fiber2.state == Fiber.State.TERM);
    fiber1.call(); // switches to fiber1 which also reaches end of function
                   // and switches back to main upon exist
    assert (fiber1.state == Fiber.State.TERM && fiber2.state == Fiber.State.TERM);
}

Если ваша функция волокна никогда yield()s, то он не является кооперативным, что означает, что как только выполнение входит в эту функцию, другие волокна не завершат свою работу.

Другие вопросы по тегам