Rahul said:
For the same what? The implementation should guarantee the static
variable is initialised once only.
[...]
for thread safety...
You have to make sure the object is fully visible before you return a
reference; you could do it like:
<error checking omitted for simplicity...>
_______________________________________________________________
template<typename T>
class once {
static T* m_state;
static pthread_mutex_t m_mtx;
public:
static T* get() {
T* local = ATOMIC_LOADPTR_MBDEPENDS(&m_state);
if (local == NULL) {
pthread_mutex_lock(&m_mtx);
if ((local = m_state) == NULL) {
try {
local = new T;
} catch (...) {
pthread_mutex_unlock(&m_mtx);
throw;
}
ATOMIC_STOREPTR_MBRELEASE(&m_state, local);
}
pthread_mutex_unlock(&m_mtx);
}
return local;
}
};
template<typename T>
T* once<T>::m_state = NULL;
template<typename T>
pthread_mutex_t once<T>::m_mtx = PTHREAD_MUTEX_INITIALIZER;
_______________________________________________________________
The 'ATOMIC_LOADPTR_MBDEPENDS()' function performs an atomic pointer load
followed by a data-dependant memory-barrier (e.g., read_barrier_depends() in
Linux). The 'ATOMIC_STOREPTR_MBRELEASE()' function executes a release
memory-barrier (e.g., wmb() in Linux or #LoadStore | #StoreStore in SPARC)
followed by an atomic pointer store. This is necessary to maintain proper
memory visibility of the object your storing/loading to/from the
'once<T>::m_state' member...