Possible to define a function-like macro with a variable body?

后端 未结 4 1788
小鲜肉
小鲜肉 2020-12-18 00:40

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

相关标签:
4条回答
  • 2020-12-18 00:42

    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);
    
    0 讨论(0)
  • 2020-12-18 00:46

    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();
    
    0 讨论(0)
  • 2020-12-18 00:52

    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.

    0 讨论(0)
  • 2020-12-18 00:53

    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.

    0 讨论(0)
提交回复
热议问题