... Recently, I changed Stackless Python to be safe for any recursive object built from lists, tuples, dictionaries, tracebacks and frames.
The implementation is not Stackless Python dependant and very efficient (for my eyes at least).
For efficiency, locality and minimum changes to five modules, it is implemented as two embracing macroes which are stuffed around the bodies of the deallocator methods, that makes just 3-4 lines of change for every module. (Well, the macro *can* be expanded if you like that more)
It's a nice approach, but I'd rather see you put the bulk of the Py_TRASHCAN_SAFE_END macro into a real function or two, invoked from the macro. This code is only going to get hairier if GregS takes up his free-threading quest again. Like
#define Py_TRASHCAN_SAFE_END(op) \ ;} \ else \ /* call a function to enqueue op, & maybe create list */ \ --_PyTrash_delete_nesting; \ if (_PyTrash_delete_later && _PyTrash_delete_nesting <= 0) \ /* call a function to (maybe) clean up */ \ } \
The first function only gets called when the nesting level hits (exactly) 50, and the 2nd function only when something got enqueued and the stack has completely unwound again. These should be infrequent enough that inline expansion doesn't buy much -- except the inability to set a useful breakpoint when the code fails to work <wink>.