Search code examples
cmultithreadingthread-safetyc11c17

Is there something that resembles std::lock_guard in native C?


In C++ it's recommended to use lock_guard as it ensures when the object is destroyed it unlocks the mutex.

Is there a way to implement the same thing in C? Or do we have to just implement it manually:

lock mutex

Do something on a global variable

unlock mutex

#include <stdio.h>
#include <threads.h>

long long x = 0;
mtx_t m;
static void do1()  {
   mtx_lock(&m); 
   for(int i = 0; i < 100; i++){
       x = x +1;
   }
   mtx_unlock(&m);
}

static void do2()  {
   mtx_lock(&m); 
   x = x / 3;
   mtx_unlock(&m);
}

int main(int argc, char *argv[])
{ 
   mtx_init(&m, mtx_plain);
   thrd_t thr1; 
   thrd_t thr2;
   thrd_create(&thr1, do1, 0);
   thrd_create(&thr2, do2, 0);
   thrd_join(&thr2, 0);
   thrd_join(&thr1, 0);
   return 0;
}

Solution

  • std::lock_guard is an example of a general C++ concept known as RAII. C++ programmers need this because a C++ function may be exited in ways the programmer didn't write themselves, via an exception being thrown.

    C does not have exceptions, so a concept like RAII, despite its merits and utility, isn't really needed. To accomplish this sort of paired action in C you'll need to call the two functions yourself. How you do it exactly is entirely up to you. For instance, you can defer the locking to a wrapper function that accepts a callback:

    static inline void do_locked( void (*cb)(void) ) {
       mtx_lock(&m); 
       cb();
       mtx_unlock(&m);
    }
    
    static inline void do2_impl(void) {
       x = x / 3;
    }
    
    static void do2()  {
        do_locked(do2_impl);
    }
    

    Discipline to keep your code well structured is all it takes really, even if you don't have the same toolbox C++ gives you.