What is the significance of having a function reentrant in a single-threaded environment?
I understood that for a function to be reentrant it needs to be able to be interrupted, entered by another thread, and resume without having any undefined or undesired side effects.
I read this question Threadsafe vs re-entrant. But it's not clear how can this actually happen in code:
you can have reentrance problems in a single-threaded program if you use callbacks or recursive functions.
Suppose we put multi-threading aside. This function can be said to be non re-entrant:
void bar() {
static bool inside_function;
inside_function = true;
assert (inside_function == true)
inside_function = false;
}
Without recursion and callbacks this isn't an issue. Though once you add recursion the non-re-entrancy of the function matters:
void foo(bool repeat = true) {
static bool inside_function;
inside_function = true;
if (repeat) foo(false);
// do some stuff
// assert( inside_function == true )
std::cout << inside_function << "\n";
inside_function = false;
}
Suppose do some stuff
depends on inside_function == true
, then this recursion fails (output is 1 0
). Note that this is a contrived example for illustration and with callbacks the issue is not always that obvious:
struct Foo {
bool inside = false;
void operator()(Foo& f,bool call = true) {
inside = true;
if(call) f(*this,false);
std::cout << "inside operator() : " << inside << "\n";
if (inside == false) std::cout << "something went wrong !!!\n";
inside = false;
}
};
int main() {
Foo f;
f(f);
}
Output:
inside operator() : 1
inside operator() : 0
something went wrong !!!
In a single threaded environment thread-safety is not an issue, but re-entrancy is when recursion or callbacks are used.