c++cmultithreadingreentrancy

What is the significance of having a function reentrant in a single-threaded environment?


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.


Solution

  • 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.