login
Header Space

 
 

Creating macros for function definitions && calls

June 21, 2007 - 1:22pm
Submitted by Anonymous on June 21, 2007 - 1:22pm.
Applications and Utilities

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

June 22, 2007 - 11:36pm
Anonymous (not verified)

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

June 23, 2007 - 8:12am
Anonymous (not verified)

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

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
speck-geostationary