Spec-Zone.ru › Elisp

Нелокальные выходы в модулях

Emacs Lisp поддерживает нелокальные выходы, при которых управление программой передаётся из одной точки программы в другую, удалённую точку. См. Нелокальные выходы. Поэтому функции Lisp, вызываемые вашим модулем, могут выполнять нелокальный выход, вызывая signal или throw, и функции вашего модуля должны правильно обрабатывать такие нелокальные выходы. Такая обработка необходима, поскольку программы на C в этих случаях не будут автоматически освобождать ресурсы и выполнять другую очистку; код модуля должен делать это самостоятельно. API модуля предоставляет средства для этого, описанные в данном подразделе. Как правило, они доступны начиная с Emacs 25; для тех из них, которые появились в более поздних выпусках, явно указана первая версия Emacs, в которой они стали частью API.

Когда некоторый код Lisp, вызванный функцией модуля, сигнализирует об ошибке или выполняет throw, нелокальный выход перехватывается, а ожидающий выход и связанные с ним данные сохраняются в окружении. Пока в окружении ожидает нелокальный выход, любая функция API модуля, вызванная с указателем на это окружение, немедленно возвращает управление без выполнения каких-либо действий (исключение составляют функции non_local_exit_check, non_local_exit_get и non_local_exit_clear). Если после этого функция вашего модуля ничего не делает и возвращается в Emacs, ожидающий нелокальный выход заставит Emacs обработать его: сигнализировать об ошибке или выполнить throw к соответствующему catch.

Таким образом, простейшая «обработка» нелокальных выходов в функциях модулей — не предпринимать ничего особенного и позволить остальной части кода выполняться так, как если бы ничего не произошло. Однако это может привести к двум видам проблем:

  • Функция вашего модуля может использовать неинициализированные или неопределённые значения, поскольку функции API немедленно возвращают управление, не предоставляя ожидаемых результатов.
  • Ваш модуль может допустить утечку ресурсов, поскольку у него может не быть возможности освободить их.

Поэтому мы рекомендуем функциям вашего модуля проверять условия нелокального выхода и обрабатывать их с помощью описанных ниже функций.

Функция: enum emacs_funcall_exit non_local_exit_check (emacs_env *env)

Эта функция возвращает тип условия нелокального выхода, сохранённого в env. Возможны следующие значения:

emacs_funcall_exit_return

Последняя функция API завершилась нормально.

emacs_funcall_exit_signal

Последняя функция API сигнализировала об ошибке.

emacs_funcall_exit_throw

Последняя функция API завершилась с помощью throw.

Функция: enum emacs_funcall_exit non_local_exit_get (emacs_env *env, emacs_value *symbol, emacs_value *data)

Эта функция возвращает тип условия нелокального выхода, сохранённого в env, как и non_local_exit_check, но также возвращает полную информацию о нелокальном выходе, если он есть. Если возвращаемое значение — emacs_funcall_exit_signal, функция сохраняет символ ошибки в *symbol, а данные ошибки — в *data (см. Как сигнализировать об ошибке). Если возвращаемое значение — emacs_funcall_exit_throw, функция сохраняет символ метки catch в *symbol, а значение throw — в *data. Если возвращаемое значение — emacs_funcall_exit_return, функция ничего не сохраняет в памяти, на которую указывают эти аргументы. Если функции не удаётся выделить память для symbol или data, она сохраняет значение, представляющее символ module-out-of-memory, в *symbol, сохраняет значение, представляющее nil, в *data и возвращает emacs_funcall_exit_signal.

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

Обнаружив ожидающий нелокальный выход, функция вашего модуля может либо вернуться в Emacs (предварительно выполнив необходимую локальную очистку), либо попытаться восстановиться после нелокального выхода. В этом помогут следующие функции API.

Функция: void non_local_exit_clear (emacs_env *env)

Эта функция очищает ожидающие условия нелокального выхода и данные из env. После её вызова функции API модуля будут работать в обычном режиме. Используйте эту функцию, если функция вашего модуля может восстановиться после нелокальных выходов из вызываемых ею функций Lisp и продолжить работу, а также перед вызовом любой из следующих двух функций (или любых других функций API, если вы хотите, чтобы они выполняли свои предусмотренные действия при ожидающем нелокальном выходе).

Функция: void non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)

Эта функция выполняет throw к символу catch Lisp, представленному tag, передавая ему value в качестве возвращаемого значения. Как правило, функция вашего модуля должна вскоре завершиться после вызова этой функции. Один из вариантов использования этой функции — повторно выполнить throw для нелокального выхода из одной из вызванных функций API или Lisp.

Функция: void non_local_exit_signal (emacs_env *env, emacs_value symbol, emacs_value data)

Эта функция сигнализирует об ошибке, представленной символом ошибки symbol, с указанными данными ошибки data. Функция модуля должна вскоре завершиться после вызова этой функции. Эта функция может быть полезна, например, для сигнализации об ошибках из функций модуля в Emacs.

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Module-Nonlocal.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API