
"Roland Schwarz" <roland.schwarz@chello.at> wrote in message news:4544CC77.9060009@chello.at...
Triggered by the question how to do static initialization of a mutex, I tried to write one that is.
Here is something you can try... pseudo-code ----------------- namespace atomic { template<typename T> class var; template<typename T> class once; namespace mb { enum naked_e { naked }; enum fence_e { fence }; enum release_e { release }; enum depends_e { depends }; } namespace externlib_api { class hashed_mutex; template<typename T> extern T load(T volatile*, mb::naked_e) const throw(); template<typename T> extern T load(T volatile*, mb::depends_e) const throw(); template<typename T> extern void store(T volatile*, T const&, mb::release_e) throw(); template<typename T> extern void store(T volatile*, T const&, mb::naked_e) throw(); } template<typename T> class var { mutable T volatile m_state; public: var() throw() {} var(T const &state) throw() : m_state(state) {} public: inline T load(mb::depends_e) const throw() { return externlib_api::load(&m_state, mb::depends); } inline T load(mb::naked_e) const throw() { return externlib_api::load(&m_state, mb::naked); } public: inline void store(T const &xchg, mb::fence_e) throw() { externlib_api::store(&m_state, xchg, mb::fence); } inline void store(T const &xchg, mb::naked_e) throw() { externlib_api::store(&m_state, xchg, mb::naked); } }; template<typename T> class once { var<T> m_state; public: once() throw() : m_state(0) {} ~once() throw() { T *local = m_state.load(mb::naked); if (local) { // assume this is statically out of scope try { delete local; } catch(...) { assert(false); throw; } } } public: // atomic load / thread-saftey: strong T* load() const { T *local = m_state.load(mb::depends); if (! local) { externlib_api::hashed_mutex::guard_t const &lock(this); local = m_state.load(mb::naked); if (! local) { local = new T; m_state.store(local, mb::release); } } return local; } }; } // usage... static atomic::once<foo> g_foo; void some_threads(...) { for(;;) { // whatever... foo *myfoo = g_foo.load(); } } Any thoughts?