I've been looking at the GCC docs for defining macros and it looks like what I want isn't possible, but I figure if it is, someone here would know.
What I want to do is define this macro:
synchronized(x) {
  do_thing();
}
Which expands to:
{
    pthread_mutex_lock(&x);
    do_thing();
    pthread_mutex_unlock(&x);
}
In C++ I could just make a SynchronizedBlock object that gets the lock in its constructor and unlocks in the destructor, but I have no idea how to do it in C.
I realize I could use a function pointer in the form synchronized(x, &myfunction);, but my goal is to make some C code look as much like Java as possible. And yes, I know this is evil.
EDIT: Changed to nategoose's version
#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)
And you can use it like this:
synchronized(x) {
    do_thing(x);
}
Or even without braces
synchronized(x)
    do_thing();
                        Here's a start, but you may need to tweak it:
#define synchronized(lock, func, args...) do { \
    pthread_mutex_lock(&(lock)); \
    func(##args); \
    pthread_mutex_unlock(&(lock)); \
} while (0)
Use like this (unfortunately, not the Java-like syntax you wanted):
synchronized(x, do_thing, arg1, arg2);
                        This was the best I came up with:
#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")
                        ));
Note that you have to use the rarely used comma operator and there are restrictions to what code can live within the (not quite java-like) synchronization code list.
Very interesting question!
I looked at the other answers and liked the one using for. I have an improvement, if I may! GCC 4.3 introduces the COUNTER macro, which we can use to generate unique variable names.
#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))
Using those macros, this code...
mutex(my_mutex) {
    foo();
}
... will expand to...
char my_mutex__0;
for (my_mutex__0 = 1, lock(my_mutex); my_mutex__0 == 1; --my_mutex__0, unlock(m)) {
    foo();
}
With my_mutex__n starting in 0 and generating a new name each time its used! You can use the same technique to create monitor-like bodies of code, with a unique-but-unknown name for the mutex.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With