James
James

Reputation: 429

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;
}

Upvotes: 5

Views: 214

Answers (1)

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.

Upvotes: 6

Related Questions