I have some code which is supposed to be a thread-safe python/c++ api. I am using the macros Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS, which expand to create save thread state and create a lock. I am releasing the lock just before method exit; once inside of if statement scope, and once at method scope.
Why does this not compile? It generates the error: error: _save was not declared in this scope at the second Py_END_ALLOW_THREADS macro.
uint8_t SerialBuffer::push_msg() { #if defined (UBUNTU) Py_BEGIN_ALLOW_THREADS #endif if (_type == ARRAY) { // array access } else if (_type == PRIORITY_QUEUE) { // queue access } else { // Placing the return statement in the preprocessor directive // has no effect. #if defined (UBUNTU) Py_END_ALLOW_THREADS #endif return FAIL; } #if defined (UBUNTU) Py_END_ALLOW_THREADS #endif return SUCCESS; } I have also tried putting the return statement inside of the #if directive scope, and this generates the same error. However, this works:
uint8_t SerialBuffer::push_msg() { #if defined (UBUNTU) Py_BEGIN_ALLOW_THREADS #endif if (_type == ARRAY) { // array access } else if (_type == PRIORITY_QUEUE) { // queue access } else { // NOTE lack of #if directive here. // Even though if this code executes the code below will not. // Seems like a relatively simple problem for lambda calculus, no? return FAIL; } #if defined (UBUNTU) Py_END_ALLOW_THREADS #endif return SUCCESS; } Edit: I'm aware that the second example does not do thread clean-up; however, it compiles.
Edit2: Py_BEGIN_ALLOW_THREADS expands to { PyThreadState *_save; _save = PyEval_SaveThread();
Py_END_ALLOW_THREADS expands to PyEval_RestoreThread(_save); } NOTE the scoping braces prepending BEGIN and appending END. Why is it the logical choice for the macro expansion to include scoping?