From 8e4e6cd9414e0ba301aad7ec24c3d01d67d391b7 Mon Sep 17 00:00:00 2001 From: Noam Postavsky Date: Sat, 10 Dec 2016 21:53:53 -0500 Subject: [PATCH v1] Clean up var watcher disabling on thread switching * src/data.c (inhibit_variable_watchers): New variable. (notify_variable_watchers): Don't notify watchers it's non-nil. * src/eval.c (set_inhibit_variable_watchers): New function. (rebind_for_thread_switch, unbind_for_thread_switch): Disable variable watchers while setting variables to thread-local values. --- src/data.c | 4 ++++ src/eval.c | 39 +++++++++++++++++++++------------------ src/lisp.h | 1 + 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/data.c b/src/data.c index 09d94f5..682a669 100644 --- a/src/data.c +++ b/src/data.c @@ -1513,12 +1513,16 @@ DEFUN ("get-variable-watchers", Fget_variable_watchers, Sget_variable_watchers, : Qnil; } +bool inhibit_variable_watchers = false; + void notify_variable_watchers (Lisp_Object symbol, Lisp_Object newval, Lisp_Object operation, Lisp_Object where) { + if (inhibit_variable_watchers) return; + symbol = Findirect_variable (symbol); ptrdiff_t count = SPECPDL_INDEX (); diff --git a/src/eval.c b/src/eval.c index f1e0ae7..15ef5ab 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3343,30 +3343,34 @@ record_unwind_protect_void (void (*function) (void)) grow_specpdl (); } +static void +set_inhibit_variable_watchers (int val) +{ + inhibit_variable_watchers = val; +} + void rebind_for_thread_switch (void) { union specbinding *bind; + ptrdiff_t count = SPECPDL_INDEX (); + record_unwind_protect_int (set_inhibit_variable_watchers, + inhibit_variable_watchers); + /* Hide implementation of thread-local variables from Lisp code. */ + inhibit_variable_watchers = true; + for (bind = specpdl; bind != specpdl_ptr; ++bind) { if (bind->kind >= SPECPDL_LET) { Lisp_Object value = specpdl_saved_value (bind); Lisp_Object sym = specpdl_symbol (bind); - bool was_trapped = - SYMBOLP (sym) - && XSYMBOL (sym)->trapped_write == SYMBOL_TRAPPED_WRITE; - /* FIXME: This is not clean, and if do_specbind signals an - error, the symbol will be left untrapped. */ - if (was_trapped) - XSYMBOL (sym)->trapped_write = SYMBOL_UNTRAPPED_WRITE; bind->let.saved_value = Qnil; do_specbind (XSYMBOL (sym), bind, value); - if (was_trapped) - XSYMBOL (sym)->trapped_write = SYMBOL_TRAPPED_WRITE; } } + unbind_to (count, Qnil); } static void @@ -3510,24 +3514,23 @@ unbind_for_thread_switch (struct thread_state *thr) { union specbinding *bind; + ptrdiff_t count = SPECPDL_INDEX (); + record_unwind_protect_int (set_inhibit_variable_watchers, + inhibit_variable_watchers); + /* Hide implementation of thread-local variables from Lisp code. */ + inhibit_variable_watchers = true; + + for (bind = thr->m_specpdl_ptr; bind > thr->m_specpdl;) { if ((--bind)->kind >= SPECPDL_LET) { Lisp_Object sym = specpdl_symbol (bind); - bool was_trapped = - SYMBOLP (sym) - && XSYMBOL (sym)->trapped_write == SYMBOL_TRAPPED_WRITE; bind->let.saved_value = find_symbol_value (sym); - /* FIXME: This is not clean, and if do_one_unbind signals an - error, the symbol will be left untrapped. */ - if (was_trapped) - XSYMBOL (sym)->trapped_write = SYMBOL_UNTRAPPED_WRITE; do_one_unbind (bind, false); - if (was_trapped) - XSYMBOL (sym)->trapped_write = SYMBOL_TRAPPED_WRITE; } } + unbind_to (count, Qnil); } DEFUN ("special-variable-p", Fspecial_variable_p, Sspecial_variable_p, 1, 1, 0, diff --git a/src/lisp.h b/src/lisp.h index 252707c..b16cada 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -605,6 +605,7 @@ INLINE bool (VECTORLIKEP) (Lisp_Object); /* Defined in data.c. */ extern _Noreturn void wrong_type_argument (Lisp_Object, Lisp_Object); extern _Noreturn void wrong_choice (Lisp_Object, Lisp_Object); +extern bool inhibit_variable_watchers; extern void notify_variable_watchers (Lisp_Object symbol, Lisp_Object newval, Lisp_Object operation, Lisp_Object where); -- 2.9.3