Есть несколько способов, которые я бы рассмотрел в первую очередь.
Один похож на фреймы исключений.Создайте для каждого потока связанный список структур.Перед вызовом функции создайте структуру в стеке и добавьте ее в конец списка.Структура содержит jmp_buf
.Вызовите setjmp
, и если он вернет 0, продолжайте работу с этой функцией, в противном случае (каким-то образом) проверьте, не является ли вы целью return-from
- если это так, затем продолжите работу с этой функцией, в противном случае очистите ваших местных жителей и longjmp
предыдущий кадр.Я думаю, что это может быть излишним, это зависит от того, насколько гибким должен быть этот return-from
.Нужно ли только возвращаться из функции, которая находится в окружающей лексической области, или мы на самом деле ищем в стеке вызовов именованную функцию, которая может или не может даже присутствовать?Если первое, я сомневаюсь, что нам это нужно.
Другая возможность состоит в том, чтобы заставить все подсчитанные ссылками типы реализовывать общий интерфейс (внутренне для языковой реализации, это - это не должно быть видимым для пользователей),Затем вы можете просто создать стек (указателей) объектов, которые требуют очистки, вместе с возможностью создавать индексные точки в этом стеке, соответствующие уровням стека вызовов.При выходе из функции вы очищаете все переменные ниже уровня стека, к которому вы возвращаетесь, просто просматривая список с разыменованием каждого из них, вместо того, чтобы переходить к очистке сегментов кода в подпрограммах над нами в стеке вызовов.Тогда вы могли бы longjmp
прямиком к цели или придумать «соглашение о вызовах», в котором возвращаемое значение, если говорить о вашем языке, фактически хранится в местоположении, определяемом параметром указателя (out-param), в то время как возвращаемое значение для C указывает, где в стеке вы возвращаетесь.Поэтому вызывающие программы проверяют, соответствует ли возвращаемое значение их собственному уровню, а если нет, немедленно возвращаются, и нет необходимости в longjmp
.Это может быть или не быть более эффективным для longjmp
, в зависимости от того, сколько уровней стека вы пропускаете, и, следовательно, сколько повторений проверки и возврата.
Эта схема немного похожа на стек очисткив Symbian / C ++.Фактически, это идет немного дальше - это не очищаемый ресурс, который должен реализовывать общий интерфейс, а то, что идет в стеке, это TCleanupItem, состоящий из функции, которая знает, как освободить ресурс, и некоторых данных для подачи вэта функция.