Есть ли метод, который вызывает раскручивание всего стека кадра в C ++? (кроме использования исключения) - PullRequest
4 голосов
/ 15 февраля 2012

Я пишу продолжение - в конкретной, сопрограммной - библиотеке. Он похож на std :: thread (за исключением того, что он кооперативный) - каждый контекст выполнения представлен в объекте продолжения.

Проблема в продолжении уничтожения объекта. Если dtor для объекта продолжения вызывается, пока контекст выполнения не вышел изящно, он должен быть принудительно закрыт контекстом, уничтожающим объект.

Таким образом, каждый объект C ++ в кадре стека не будет уничтожен должным образом. Это может не быть приятной ситуацией для всех - поэтому я решил найти решение.

В первый раз я подумал использовать исключение, чтобы развернуть кадр стека, как показано ниже. (Обратите внимание, что ниже приведен только некорректный псевдо-код.)

coroutine::~coroutine()
{
    status = FORCED_EXIT;
    switch_to(*this);
}

void coroutine::yield(coroutine& other_coroutine)
{
     // switch to other context, halt until invocation by other context
    switch_to(other_coroutine);

    if (status_ != FORCED_EXIT) {
        return; // resume
    } else {
        throw ContextClosingException;
    }
}

void coroutine::entrypoint()
{
    try {
        entry_function_();
    } catch(ContextClosingException& e) {
        switch_to(caller_coroutine);
    }
}

Однако я обнаружил критический недостаток. Любой пользовательский код, который «проглотит исключение», как показано ниже, полностью нарушит предположение о совместном планировании.

try {
    ...
} catch(...) { // ContextClosingException 
    // do nothing, just swallow exception.
}

Так что мне нужно найти другой способ вызвать раскрутку стека (или любой другой способ уничтожить объект стека в продолжении). Было бы неплохо использовать стандартный способ соответствия, но сама реализация продолжения зависит от API конкретной платформы, поэтому непереносимый способ будет приемлемым. (Я использую win32)

1 Ответ

1 голос
/ 15 февраля 2012

В стандарте C ++ нет ничего, что позволяло бы разматывать стек, кроме исключений. Сопрограммы (или поддержка corountines) могут быть предложены после C ++ 11 (о котором говорилось на конференции Going Native).

Вам придется использовать специфичные для ОС вызовы C (если они существуют, и я так не думаю), но, скорее всего, вы сами по себе с ASM. Вы можете взглянуть на библиотеку boost.context для примера решения.

...