可以用变量体定义类似函数的宏吗?

时间:2010-10-27 19:37:38

标签: c macros mutex

我一直在寻找用于定义宏的GCC docs,看起来我想要的东西是不可能的,但我想如果是的话,有人会知道。

我想要做的是定义这个宏:

synchronized(x) {
  do_thing();
}

扩展为:

{
    pthread_mutex_lock(&x);
    do_thing();
    pthread_mutex_unlock(&x);
}

在C ++中,我可以创建一个SynchronizedBlock对象,在其构造函数中获取锁定并在析构函数中解锁,但我不知道如何在C中执行此操作。

我意识到我可以使用synchronized(x, &myfunction);形式的函数指针,但我的目标是让一些C代码看起来像Java一样。是的,我知道这是邪恶的。

4 个答案:

答案 0 :(得分:16)

编辑:已更改为nategoose的版本

#define synchronized(lock) \
for (pthread_mutex_t * i_#lock = &lock; i_#lock; \
     i_#lock = NULL, pthread_mutex_unlock(i_#lock)) \
    for (pthread_mutex_lock(i_#lock); i_#lock; i_#lock = NULL)

你可以像这样使用它:

synchronized(x) {
    do_thing(x);
}

甚至没有大括号

synchronized(x)
    do_thing();

答案 1 :(得分:4)

这是一个开始,但您可能需要调整它:

#define synchronized(lock, func, args...) do { \
    pthread_mutex_lock(&(lock)); \
    func(##args); \
    pthread_mutex_unlock(&(lock)); \
} while (0)

像这样使用(遗憾的是,不是你想要的类似Java的语法):

synchronized(x, do_thing, arg1, arg2);

答案 2 :(得分:2)

非常有趣的问题!

我查看了其他答案,并喜欢使用for的答案。如果可以的话,我有所改善! GCC 4.3引入了 COUNTER 宏,我们可以用它来生成唯一的变量名。

#define CONCAT(X, Y) X##__##Y
#define CONCATWRAP(X, Y) CONCAT(X, Y)
#define UNIQUE_COUNTER(prefix) CONCATWRAP(prefix, __COUNTER__)

#define DO_MUTEX(m, counter) char counter; \
for (counter = 1, lock(m); counter == 1; --counter, unlock(m))

#define mutex(m) DO_MUTEX(m, UNIQUE_COUNTER(m))

使用这些宏,这段代码......

mutex(my_mutex) {
    foo();
}

......将扩展为......

char my_mutex__0;
for (my_mutex__0 = 1, lock(my_mutex); my_mutex__0 == 1; --my_mutex__0, unlock(m)) {
    foo();
}

my_mutex__n从0开始,每次使用时都会生成一个新名称!您可以使用相同的技术创建类似监视器的代码体,并使用唯一但未知的互斥锁名称。

答案 3 :(得分:1)

这是我提出的最好的:

#define synchronized(x, things) \
      do { \
           pthread_mutex_t * _lp = &(x); \
           pthread_mutex_lock(_lp);      \
           (things);                     \
           pthread_mutex_unlock(_lp);    \
      } while (0)

...

        synchronized(x,(
                          printf("hey buddy\n"),
                          a += b,
                          printf("bye buddy\n")
                        ));

请注意,您必须使用很少使用的逗号运算符,并且对于(不完全类似于Java的)同步代码列表中的代码存在限制。