Search code examples
c++critical-section

Is it safe to send a pointer to a CriticalSection Function? C++


I have some statics I use to check if a thread is running, and if the program wants to / can close.

Normally I would create a seperate function for each variable like so:

static              CCriticalSection crit_sec;

static bool         static_thread_a_closed = false;
static bool         static_thread_b_closed = false;
static bool         static_prog_closing = false;

static void Set_thread_a_Val(bool set_to)
{
    crit_sec.Lock();
    static_thread_a_closed = set_to;
    crit_sec.Unlock();
};

static bool Get_thread_a_Val()
{
    bool ret;

    crit_sec.Lock();
    ret = static_thread_a_closed;
    crit_sec.Unlock();

    return ret;
};

// etc etc for the others...

void thread_a::Do()
{
    //code
    Set_thread_a_Val(false);
}

void MainDlg::OnClose()
{
    //code..
    while(Get_thread_a_Val()) // ... wait
    //code..
}

I am wondering if it would be 'safe' to do this with pointers like so:

static              CCriticalSection crit_sec;

static bool         static_thread_a_closed = false;
static bool         static_thread_b_closed = false;
static bool         static_prog_closing = false;

static void Set_Bool_Val(bool* val, bool set_to)
{
    crit_sec.Lock();
    *val = set_to;
    crit_sec.Unlock();
};

static bool Get_Bool_Val(bool* val)
{
    bool ret;

    crit_sec.Lock();
    ret = *val;
    crit_sec.Unlock();

    return ret;
};

void thread_a::Do()
{
    //code
    Set_Bool_Val(&static_thread_a_closed, false);
}

void MainDlg::OnClose()
{
    //code..
    while(Get_Bool_Val(&static_thread_a_closed)) // ... wait
    //code..
}

Is the memory actually accessed when it is passed, so this will fail?

Or is it simply pass the address, meaning this would be ok?


Solution

  • The pointers are fine.

    However, there is a good chance that static_thread_a_closed will not be read a second time because C doesn't, by default, know that static_thread_a_closed can change in the while loop.

    Adding volatile keywords lets the compiler know that variables can be changed by interrupts/other threads/other processes, so that the variable must always be re-read. Otherwise, your while() might be optimized to while(1) or while(0).

    static volatile bool     static_thread_a_closed = false;
    static volatile bool     static_thread_b_closed = false;
    static volatile bool     static_prog_closing = false;
    
    static bool Get_Bool_Val(volatile bool* val)
    

    Edit: After realizing I triggered some "Volatile Hostility," I should add that in this case, the volatiles will probably not make any difference in either case. In both cases, the while() is based on the return value of a function which the compiler should not optimize out, regardless if it wants to use the cached value of the static flags.