Интернет магазин китайских планшетных компьютеров



Компьютеры - Setcontext - Пример

22 апреля 2011


Оглавление:
1. Setcontext
2. Пример



Пример ниже демонстрирует итератор, реализованный с помощью setcontext. Подобный код можно встретить достаточно редко; вместо использования setcontext для реализации кооперативной многозадачности часто используется различные библиотеки-обёртки, например, GNU Portable Threads.

#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
 
/* Функция-итератор. Вход в неё осуществляется при первом вызове
 * swapcontext, замет проходит в цикле от 0 до 9. Каждое значение сохраняется 
 * i_from_iterator, после чего производится возврат в основной цикл с помощью swapcontext. 
 * В основном цикле производится вывод значения и вызов swapcontext для возврата
 * назад в функцию. При достижении конца цикла исполнение переключается на контекст 
 * of the loop is reached, the function exits, and execution switches to the main_context1. */
void loop(
    ucontext_t *loop_context,
    ucontext_t *other_context,
    int *i_from_iterator)
{
    int i;
 
    for  {
        /* Запись счётчика цикла в место возврата итератора. */
        *i_from_iterator = i;
 
        /* Сохранение контекста цикла в ''loop_context'' и переключение на другой контекст. */
        swapcontext;
    }
} 
 
int main
{
    /* Три контекста:
     *    main_context1 : указывает на main для возврата из цикла.
     *    main_context2 : указывает на место переключения контекста в main
     *    loop_context  : указывает на место в цикле, в которое будет 
     *                        переходить управление из main. */
    ucontext_t main_context1, main_context2, loop_context;
 
    /* Стек для функции итератора. */
    char iterator_stack;
 
    /* Флаг, сообщающий о завершении итератора. */
    volatile int iterator_finished;
 
    /* Возвращаемое значение итератора. */
    volatile int i_from_iterator;
 
    /* Инициализация контекста итератора. uc_link указывает на main_context1, 
     * точку возврата при завершении итератора. */
    loop_context.uc_link          = &main_context1;
    loop_context.uc_stack.ss_sp   = iterator_stack;
    loop_context.uc_stack.ss_size = sizeof;
    getcontext;
 
    /* Заполнение loop_context, что позволяет swapcontext начать цикл. 
     * Преобразование в) необходимо для избежания  предупреждения 
     * компилятора и не влияет на поведение функции. */
    makecontext) loop,
        3, &loop_context, &main_context2, &i_from_iterator);
 
    /* Очистка флага завершения. */      
    iterator_finished = 0;
 
    /* Сохранения текущего контекста в main_context1. При завершении цикла
     * управление будет возвращено в эту точку. */
    getcontext;
 
    if  {
        /* Установка флага iterator_finished для отключения перезапуска итератора. */
        iterator_finished = 1;
 
        while  {
            /* Сохранение этой точки в main_context2 и переключение на итератор.
             * Первый вызов зачинает цикл, последующие осуществляют переключение
             * через swapcontext в цикл. */
            swapcontext;
            printf;
        }
    }
 
    return 0;
}

Примечание: данный пример не соответствует справочной странице спецификации . Функция makecontext требует, чтобы дополнительные параметры были типа int, а в примере передаются указатели. Это может привести к ошибке на 64-битных платформах > sizeof). Теоретически эти проблемы могут быть решены, но эти решения также не являются портируемыми.



Просмотров: 1719


<<< SCO
Single UNIX Specification >>>