C ++ macro in case if statement does not compile

I have some code that needs to be thread safe python / c ++ api. I use macros Py_BEGIN_ALLOW_THREADS

and Py_END_ALLOW_THREADS

, which extend to create a thread save state and create a lock. I release the lock before the method exits; once inside the scope if

and once in the scope of the method.

Why doesn't it compile? It generates an error: error: _save was not declared in this scope

in the second macro Py_END_ALLOW_THREADS

.

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 also tried to put the statement return

inside the scope #if

and it throws 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 know that the second example doesn't clean up streams; however, it compiles.

Edit2: Py_BEGIN_ALLOW_THREADS

expands to{ PyThreadState *_save; _save = PyEval_SaveThread();

Py_END_ALLOW_THREADS

expands to PyEval_RestoreThread(_save); }

SPECIFY curly braces BEGIN

appending and appending END

. Why does the logical choice for expanding a macro include scoping?

+3


source to share


1 answer


The preprocessor expands the macro Py_BEGIN_ALLOW_THREADS

into code that creates a local named object _save

.

The preprocessor extends the macro Py_END_ALLOW_THREADS

into code that it uses _save

to perform stream cleanup tasks.

If you put Py_BEGIN_ALLOW_THREADS

inside an else block, the generated code Py_END_ALLOW_THREADS

cannot see the local object _save

, so you get an error.

In the relevant topic, I recommend placing Py_BEGIN_ALLOW_THREADS

and Py_END_ALLOW_THREADS

, where, if the first is executed, then the second. The second version of the function will not perform thread cleanup tasks for Py_END_ALLOW_THREADS

if you have an array type or a priority queue type.



Try the following:

uint8_t SerialBuffer::push_msg() {

#if defined (UBUNTU)
  Py_BEGIN_ALLOW_THREADS
#endif
  uint8_t response = FAIL;

  if (_type == ARRAY) {
      // array access
      response = SUCCESS;
  } else if (_type == PRIORITY_QUEUE) {
      // queue access
      response = SUCCESS;
  }

#if defined (UBUNTU)
  Py_END_ALLOW_THREADS
#endif

  return response;
}

      

In this version, the default answer is FAIL, so you don't even need the last section section. The other if statements only set the answer to SUCCESS if all goes well.

+3


source







All Articles