Is it possible to split macro variable arguments into separate tokens? I would like to write a macro which expands into two function definitions, one which is wrapped in a pthread_mutex... forcing mutual exclusion on a given function. Note, I haven't tried compiling this yet so there may be minor errors, I wanted to see if I could get the right preprocessor output first... Here's the first attempt:
#define ATOMIC(ret, NAME, ...) \
static pthread_mutex_t NAME##_mutex=PTHREAD_MUTEX_INITIALIZER;\
ret NAME(__VA_ARGS__){ \
ret retVal; \
while(pthread_mutex_lock(&NAME ## _mutex)); \
fprintf(stderr, " !! Error Entering: %s\n",#NAME); \
retVal = NAME(__VA_ARGS__); \
pthread_mutex_unlock(&NAME ## _mutex); \
return retVal; \
} \
ret NAME ## _lock(__VA_ARGS__)
So that the usage:
ATOMIC(int, testFunc, int arg){
return 15;
}
Produces:
static pthread_mutex_t testFunc_mutex = PTHREAD_MUTEX_INITIALIZER;
int testFunc(int arg){
int retVal;
while(pthread_mutex_lock(&testFunc_mutex))
fprintf(stderr, " !! Error Entering: %s\n","testFunc");
retVal = testFunc(int arg);
pthread_mutex_unlock(&testFunc_mutex);
return retVal;
}
int testFunc_lock(int arg){
return 15;
}
The problem is that I'm not sure if there is a way to drop the type from the argument list when calling the 'generated' function. Does anyone know if this is possible? Or have a good/better way to do what I'm attempting?
Thanks,
Bryan.
Here's one way of doing what
Here's one way of doing what you want. It uses GCC attributes to execute code when the function exits.
Simply add ATOMIC_FUNC; at the start of a function to make it atomic.
Untested code. It spits out a warning, and I have no idea why. I'll leave it to you to fix it. ;)
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #define CLEANUP(__func) __attribute__((cleanup(__func))) #define UNUSED __attribute__((unused)) #define NORET __attribute__((noreturn)) #define ATOMIC_FUNC \ static pthread_mutex_t __mutex = PTHREAD_MUTEX_INITIALIZER; \ pthread_mutex_t UNUSED CLEANUP(__func_unlock_mutex) *__mutex_ptr = &__mutex; \ int UNUSED __dummy = pthread_mutex_lock(&__mutex) && \ __func_lock_err(__FUNCTION__); static inline void __func_unlock_mutex(pthread_mutex_t *mutex) { printf("DEBUG: Leaving function.\n"); pthread_mutex_unlock(mutex); } static inline NORET int __func_lock_err(const char *name) { fprintf(stderr, "Error locking mutex for function %s!\n", name); exit(1); } int test1(int arg) { int foo; /* you can add vars before... */ ATOMIC_FUNC; int bar; /* ...and after :) */ printf("Y halo thar.\n"); return arg; }To get rid of the
To get rid of the warning:
static inline void __func_unlock_mutex(pthread_mutex_t **mutex) { printf("DEBUG: Leaving function.\n"); pthread_mutex_unlock(*mutex); }