
This is a short illustration of the atomic_ops package.
The following is a correct implementation of the "double-checked
locking" idiom in C. It is portable to all platforms on which
atomic_ops has been implemented.
The example demonstrates how to safely initialize a variable x
in a pthreads environment, such that the initialization occurs only
on first use. The function get_x always returns the value
associated with of expensive_func(42.0), but computes it
at most once, and does not compute it if get_x is not called.
The "double-checked locking" pattern avoids lock acquisitions after
the initialization. Hence calls after the first one are appreciably
cheaper (on most platforms) than simply acquiring the lock
unconditionally.
A naive implementation which manipulates the is_initialized
flag is incorrect, and may fail due to compiler or processor reordering
of memory operations. (On most common hardware this is
extremely rare, but possible.)
#include <atomic_ops.h>
#include <pthread.h>
double x;
pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER;
extern double expensive_func(double);
volatile AO_t is_initialized = 0;
double get_x(void)
{
if (!AO_load_acquire_read(&is_initialized)) {
pthread_mutex_lock(&l);
if (!is_initialized) {
x = expensive_func(42.0);
AO_store_release_write (&is_initialized, 1);
}
pthread_mutex_unlock(&l);
}
return x;
}

|