Есть что-то, что напоминает std :: lock_guard в родном C? - PullRequest
3 голосов
/ 27 марта 2019

В C ++ рекомендуется использовать lock_guard, так как он гарантирует, что когда объект уничтожен, он разблокирует мьютекс.

Есть ли способ реализовать то же самое в C?Или мы должны просто реализовать это вручную:

заблокировать мьютекс

Сделать что-то с глобальной переменной

разблокировать мьютекс

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

1 Ответ

5 голосов
/ 27 марта 2019

std::lock_guard является примером общей концепции C ++, известной как RAII. Программисты C ++ нуждаются в этом, потому что функция C ++ может быть закрыта способами, которые программист не написал сам, через исключение.

C не имеет исключений, поэтому такая концепция, как RAII, несмотря на ее достоинства и полезность, на самом деле не нужна. Чтобы выполнить такое парное действие в C, вам нужно вызвать обе функции самостоятельно. Как именно вы это делаете, полностью зависит от вас. Например, вы можете отложить блокировку до функции-оболочки, которая принимает обратный вызов:

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

Дисциплина для поддержания хорошей структурированности вашего кода - это все, что нужно на самом деле, даже если у вас нет того же набора инструментов, который дает вам C ++.

...