Я пишу продолжение - в конкретной, сопрограммной - библиотеке. Он похож на 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)