While playing with glibc I noticed one interesting technique. It is based on gcc's extension that allows you to declare weak symbols. In essence it works like this: extern void weak_f (void) __attribute__ ((weak)); int main () { if (weak_f) { weak_f (); } } When you link such code ld won't complain if weak_f is unresolved. Plus you can check at run-time if symbol has been resolved as shown above. Interesting effects can be achieved using this technique. For example you can make some code thread-safe on-demand. You compile this code once and depending on kind of application it is used in it automatically becomes multi-threaded or single-threaded: #include <pthread.h> extern "C" int pthread_create (pthread_t*, const pthread_attr_t*, void* (*)(void*), void*) __attribute__ ((weak)); extern "C" int pthread_mutex_init (pthread_mutex_t*, const pthread_mutexattr_t*) __attribute__ ((weak)); extern "C" int pthread_mutex_lock (pthread_mutex_t*) __attribute__ ((weak)); extern "C" int pthread_mutex_unlock (pthread_mutex_t*) __attribute__ ((weak)); extern "C" int pthread_mutex_destroy (pthread_mutex_t*) __attribute__ ((weak)); class foo { public: foo () { if (pthread_create) pthread_mutex_init (&m_, 0); } ~foo () { if (pthread_create) pthread_mutex_destroy (&m_); } bar () { if (pthread_create) pthread_mutex_lock (&m_); // ... if (pthread_create) pthread_mutex_unlock (&m_); } private: pthread_mutex_t m_; // some other data that mutex protects }; Now if you link your code with libpthread, foo is automatically multi-thread-safe. If you don't then all the calls to mutex API are skipped. This could be especially nice if class foo is in the library that is used by both kinds of applications.
---------------------------
Function Pointer Syntax
The syntax for declaring a function pointer might seem messy at first, but in most cases it's really quite straight-forward once you understand what's going on. Let's look at a simple example:void (*foo)(int);In this example, foo is a pointer to a function taking one argument, an integer, and that returns void. It's as if you're declaring a function called "*foo", which takes an int and returns void; now, if *foo is a function, then foo must be a pointer to a function. (Similarly, a declaration like int *x can be read as *x is an int, so x must be a pointer to an int.)
The key to writing the declaration for a function pointer is that you're just writing out the declaration of a function but with (*func_name) where you'd normally just put func_name.
Reading Function Pointer Declarations
Sometimes people get confused when more stars are thrown in:void *(*foo)(int *);Here, the key is to read inside-out; notice that the innermost element of the expression is *foo, and that otherwise it looks like a normal function declaration. *foo should refer to a function that returns a void * and takes an int *. Consequently, foo is a pointer to just such a function.
The argument expected by pthread_create
is,
void *(*)(void *)
that is a pointer to function accepting a void pointer and returning a void pointer.