diff options
| author | Philipp Stephani | 2018-02-11 21:38:22 +0100 |
|---|---|---|
| committer | Philipp Stephani | 2020-01-03 19:24:10 +0100 |
| commit | 48ffef5ef4b34799941a033591ea827d40025939 (patch) | |
| tree | 67b00c1bc546f3c9ef601c10db634da3094f7f57 /src | |
| parent | 2b6d702e5d2d572640c6bcd43f54138bacbe7ac8 (diff) | |
| download | emacs-48ffef5ef4b34799941a033591ea827d40025939.tar.gz emacs-48ffef5ef4b34799941a033591ea827d40025939.zip | |
Implement finalizers for module functions (Bug#30373)
* src/module-env-28.h: Add new module environment functions to
module environment for Emacs 28.
* src/emacs-module.h.in: Document that 'emacs_finalizer' also works
for function finalizers.
* src/emacs-module.c (CHECK_MODULE_FUNCTION): New function.
(struct Lisp_Module_Function): Add finalizer data member.
(module_make_function): Initialize finalizer.
(module_get_function_finalizer)
(module_set_function_finalizer): New module environment functions.
(module_finalize_function): New function.
(initialize_environment): Initialize new environment functions.
* src/alloc.c (cleanup_vector): Call potential module function
finalizer during garbage collection.
* test/data/emacs-module/mod-test.c (signal_error): New helper
function.
(memory_full): Use it.
(finalizer): New example function finalizer.
(Fmod_test_make_function_with_finalizer)
(Fmod_test_function_finalizer_calls): New test module functions.
(emacs_module_init): Define them.
* test/src/emacs-module-tests.el (module/function-finalizer): New unit
test.
* doc/lispref/internals.texi (Module Functions): Document new
functionality.
(Module Misc): Move description of 'emacs_finalizer' type to 'Module
Functions' node, and add a reference to it.
* etc/NEWS: Mention new functionality.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 6 | ||||
| -rw-r--r-- | src/emacs-module.c | 36 | ||||
| -rw-r--r-- | src/emacs-module.h.in | 4 | ||||
| -rw-r--r-- | src/lisp.h | 1 | ||||
| -rw-r--r-- | src/module-env-28.h | 8 |
5 files changed, 53 insertions, 2 deletions
diff --git a/src/alloc.c b/src/alloc.c index dbe37f44d7c..f59f8cbde9a 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3027,6 +3027,12 @@ cleanup_vector (struct Lisp_Vector *vector) | |||
| 3027 | if (uptr->finalizer) | 3027 | if (uptr->finalizer) |
| 3028 | uptr->finalizer (uptr->p); | 3028 | uptr->finalizer (uptr->p); |
| 3029 | } | 3029 | } |
| 3030 | else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MODULE_FUNCTION)) | ||
| 3031 | { | ||
| 3032 | ATTRIBUTE_MAY_ALIAS struct Lisp_Module_Function *function | ||
| 3033 | = (struct Lisp_Module_Function *) vector; | ||
| 3034 | module_finalize_function (function); | ||
| 3035 | } | ||
| 3030 | } | 3036 | } |
| 3031 | 3037 | ||
| 3032 | /* Reclaim space used by unmarked vectors. */ | 3038 | /* Reclaim space used by unmarked vectors. */ |
diff --git a/src/emacs-module.c b/src/emacs-module.c index bbb0e3dadd9..3855a33f254 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c | |||
| @@ -327,6 +327,12 @@ static bool module_assertions = false; | |||
| 327 | MODULE_HANDLE_NONLOCAL_EXIT (error_retval) | 327 | MODULE_HANDLE_NONLOCAL_EXIT (error_retval) |
| 328 | 328 | ||
| 329 | static void | 329 | static void |
| 330 | CHECK_MODULE_FUNCTION (Lisp_Object obj) | ||
| 331 | { | ||
| 332 | CHECK_TYPE (MODULE_FUNCTIONP (obj), Qmodule_function_p, obj); | ||
| 333 | } | ||
| 334 | |||
| 335 | static void | ||
| 330 | CHECK_USER_PTR (Lisp_Object obj) | 336 | CHECK_USER_PTR (Lisp_Object obj) |
| 331 | { | 337 | { |
| 332 | CHECK_TYPE (USER_PTRP (obj), Quser_ptrp, obj); | 338 | CHECK_TYPE (USER_PTRP (obj), Quser_ptrp, obj); |
| @@ -478,6 +484,7 @@ struct Lisp_Module_Function | |||
| 478 | ptrdiff_t min_arity, max_arity; | 484 | ptrdiff_t min_arity, max_arity; |
| 479 | emacs_function subr; | 485 | emacs_function subr; |
| 480 | void *data; | 486 | void *data; |
| 487 | emacs_finalizer finalizer; | ||
| 481 | } GCALIGNED_STRUCT; | 488 | } GCALIGNED_STRUCT; |
| 482 | 489 | ||
| 483 | static struct Lisp_Module_Function * | 490 | static struct Lisp_Module_Function * |
| @@ -511,6 +518,7 @@ module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity, | |||
| 511 | function->max_arity = max_arity; | 518 | function->max_arity = max_arity; |
| 512 | function->subr = func; | 519 | function->subr = func; |
| 513 | function->data = data; | 520 | function->data = data; |
| 521 | function->finalizer = NULL; | ||
| 514 | 522 | ||
| 515 | if (docstring) | 523 | if (docstring) |
| 516 | function->documentation = build_string_from_utf8 (docstring); | 524 | function->documentation = build_string_from_utf8 (docstring); |
| @@ -522,6 +530,32 @@ module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity, | |||
| 522 | return lisp_to_value (env, result); | 530 | return lisp_to_value (env, result); |
| 523 | } | 531 | } |
| 524 | 532 | ||
| 533 | static emacs_finalizer | ||
| 534 | module_get_function_finalizer (emacs_env *env, emacs_value arg) | ||
| 535 | { | ||
| 536 | MODULE_FUNCTION_BEGIN (NULL); | ||
| 537 | Lisp_Object lisp = value_to_lisp (arg); | ||
| 538 | CHECK_MODULE_FUNCTION (lisp); | ||
| 539 | return XMODULE_FUNCTION (lisp)->finalizer; | ||
| 540 | } | ||
| 541 | |||
| 542 | static void | ||
| 543 | module_set_function_finalizer (emacs_env *env, emacs_value arg, | ||
| 544 | emacs_finalizer fin) | ||
| 545 | { | ||
| 546 | MODULE_FUNCTION_BEGIN (); | ||
| 547 | Lisp_Object lisp = value_to_lisp (arg); | ||
| 548 | CHECK_MODULE_FUNCTION (lisp); | ||
| 549 | XMODULE_FUNCTION (lisp)->finalizer = fin; | ||
| 550 | } | ||
| 551 | |||
| 552 | void | ||
| 553 | module_finalize_function (const struct Lisp_Module_Function *func) | ||
| 554 | { | ||
| 555 | if (func->finalizer != NULL) | ||
| 556 | func->finalizer (func->data); | ||
| 557 | } | ||
| 558 | |||
| 525 | static emacs_value | 559 | static emacs_value |
| 526 | module_funcall (emacs_env *env, emacs_value func, ptrdiff_t nargs, | 560 | module_funcall (emacs_env *env, emacs_value func, ptrdiff_t nargs, |
| 527 | emacs_value *args) | 561 | emacs_value *args) |
| @@ -1329,6 +1363,8 @@ initialize_environment (emacs_env *env, struct emacs_env_private *priv) | |||
| 1329 | env->make_time = module_make_time; | 1363 | env->make_time = module_make_time; |
| 1330 | env->extract_big_integer = module_extract_big_integer; | 1364 | env->extract_big_integer = module_extract_big_integer; |
| 1331 | env->make_big_integer = module_make_big_integer; | 1365 | env->make_big_integer = module_make_big_integer; |
| 1366 | env->get_function_finalizer = module_get_function_finalizer; | ||
| 1367 | env->set_function_finalizer = module_set_function_finalizer; | ||
| 1332 | Vmodule_environments = Fcons (make_mint_ptr (env), Vmodule_environments); | 1368 | Vmodule_environments = Fcons (make_mint_ptr (env), Vmodule_environments); |
| 1333 | return env; | 1369 | return env; |
| 1334 | } | 1370 | } |
diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in index 7065f13f2b1..b5ddd7d5fd8 100644 --- a/src/emacs-module.h.in +++ b/src/emacs-module.h.in | |||
| @@ -90,8 +90,8 @@ typedef emacs_value (*emacs_function) (emacs_env *env, ptrdiff_t nargs, | |||
| 90 | void *data) | 90 | void *data) |
| 91 | EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL (1); | 91 | EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL (1); |
| 92 | 92 | ||
| 93 | /* Function prototype for module user-pointer finalizers. These must | 93 | /* Function prototype for module user-pointer and function finalizers. |
| 94 | not throw C++ exceptions. */ | 94 | These must not throw C++ exceptions. */ |
| 95 | typedef void (*emacs_finalizer) (void *data) EMACS_NOEXCEPT; | 95 | typedef void (*emacs_finalizer) (void *data) EMACS_NOEXCEPT; |
| 96 | 96 | ||
| 97 | /* Possible Emacs function call outcomes. */ | 97 | /* Possible Emacs function call outcomes. */ |
diff --git a/src/lisp.h b/src/lisp.h index 356692d53a1..36bb79d67e1 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4244,6 +4244,7 @@ extern Lisp_Object module_function_documentation | |||
| 4244 | (struct Lisp_Module_Function const *); | 4244 | (struct Lisp_Module_Function const *); |
| 4245 | extern module_funcptr module_function_address | 4245 | extern module_funcptr module_function_address |
| 4246 | (struct Lisp_Module_Function const *); | 4246 | (struct Lisp_Module_Function const *); |
| 4247 | extern void module_finalize_function (const struct Lisp_Module_Function *); | ||
| 4247 | extern void mark_modules (void); | 4248 | extern void mark_modules (void); |
| 4248 | extern void init_module_assertions (bool); | 4249 | extern void init_module_assertions (bool); |
| 4249 | extern void syms_of_module (void); | 4250 | extern void syms_of_module (void); |
diff --git a/src/module-env-28.h b/src/module-env-28.h index dec8704edde..a2479a8f744 100644 --- a/src/module-env-28.h +++ b/src/module-env-28.h | |||
| @@ -1,3 +1,11 @@ | |||
| 1 | /* Add module environment functions newly added in Emacs 28 here. | 1 | /* Add module environment functions newly added in Emacs 28 here. |
| 2 | Before Emacs 28 is released, remove this comment and start | 2 | Before Emacs 28 is released, remove this comment and start |
| 3 | module-env-29.h on the master branch. */ | 3 | module-env-29.h on the master branch. */ |
| 4 | |||
| 5 | void (*(*EMACS_ATTRIBUTE_NONNULL (1) | ||
| 6 | get_function_finalizer) (emacs_env *env, | ||
| 7 | emacs_value arg)) (void *) EMACS_NOEXCEPT; | ||
| 8 | |||
| 9 | void (*set_function_finalizer) (emacs_env *env, emacs_value arg, | ||
| 10 | void (*fin) (void *) EMACS_NOEXCEPT) | ||
| 11 | EMACS_ATTRIBUTE_NONNULL (1); | ||