Chris@16: #ifndef BOOST_SERIALIZATION_SINGLETON_HPP Chris@16: #define BOOST_SERIALIZATION_SINGLETON_HPP Chris@16: Chris@16: /////////1/////////2///////// 3/////////4/////////5/////////6/////////7/////////8 Chris@16: // singleton.hpp Chris@16: // Chris@16: // Copyright David Abrahams 2006. Original version Chris@16: // Chris@16: // Copyright Robert Ramey 2007. Changes made to permit Chris@16: // application throughout the serialization library. Chris@16: // Chris@16: // Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // The intention here is to define a template which will convert Chris@16: // any class into a singleton with the following features: Chris@16: // Chris@16: // a) initialized before first use. Chris@16: // b) thread-safe for const access to the class Chris@16: // c) non-locking Chris@16: // Chris@16: // In order to do this, Chris@16: // a) Initialize dynamically when used. Chris@16: // b) Require that all singletons be initialized before main Chris@16: // is called or any entry point into the shared library is invoked. Chris@16: // This guarentees no race condition for initialization. Chris@16: // In debug mode, we assert that no non-const functions are called Chris@16: // after main is invoked. Chris@16: // Chris@16: Chris@16: // MS compatible compilers support #pragma once Chris@101: #if defined(_MSC_VER) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable : 4511 4512) Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: namespace serialization { Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////// Chris@16: // Provides a dynamically-initialized (singleton) instance of T in a Chris@16: // way that avoids LNK1179 on vc6. See http://tinyurl.com/ljdp8 or Chris@16: // http://lists.boost.org/Archives/boost/2006/05/105286.php for Chris@16: // details. Chris@16: // Chris@16: Chris@16: // singletons created by this code are guarenteed to be unique Chris@16: // within the executable or shared library which creates them. Chris@16: // This is sufficient and in fact ideal for the serialization library. Chris@16: // The singleton is created when the module is loaded and destroyed Chris@16: // when the module is unloaded. Chris@16: Chris@16: // This base class has two functions. Chris@16: Chris@16: // First it provides a module handle for each singleton indicating Chris@16: // the executable or shared library in which it was created. This Chris@16: // turns out to be necessary and sufficient to implement the tables Chris@16: // used by serialization library. Chris@16: Chris@16: // Second, it provides a mechanism to detect when a non-const function Chris@16: // is called after initialization. Chris@16: Chris@16: // make a singleton to lock/unlock all singletons for alteration. Chris@16: // The intent is that all singletons created/used by this code Chris@16: // are to be initialized before main is called. A test program Chris@16: // can lock all the singletons when main is entereed. This any Chris@16: // attempt to retieve a mutable instances while locked will Chris@16: // generate a assertion if compiled for debug. Chris@16: Chris@16: class singleton_module : Chris@16: public boost::noncopyable Chris@16: { Chris@16: private: Chris@16: static bool & get_lock(){ Chris@16: static bool lock = false; Chris@16: return lock; Chris@16: } Chris@16: public: Chris@16: // static const void * get_module_handle(){ Chris@16: // return static_cast(get_module_handle); Chris@16: // } Chris@16: static void lock(){ Chris@16: get_lock() = true; Chris@16: } Chris@16: static void unlock(){ Chris@16: get_lock() = false; Chris@16: } Chris@16: static bool is_locked() { Chris@16: return get_lock(); Chris@16: } Chris@16: }; Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: template Chris@16: class singleton_wrapper : public T Chris@16: { Chris@16: public: Chris@16: static bool m_is_destroyed; Chris@16: ~singleton_wrapper(){ Chris@16: m_is_destroyed = true; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: bool detail::singleton_wrapper< T >::m_is_destroyed = false; Chris@16: Chris@16: } // detail Chris@16: Chris@16: template Chris@16: class singleton : public singleton_module Chris@16: { Chris@16: private: Chris@16: BOOST_DLLEXPORT static T & instance; Chris@16: // include this to provoke instantiation at pre-execution time Chris@16: static void use(T const &) {} Chris@16: BOOST_DLLEXPORT static T & get_instance() { Chris@16: static detail::singleton_wrapper< T > t; Chris@16: // refer to instance, causing it to be instantiated (and Chris@16: // initialized at startup on working compilers) Chris@16: BOOST_ASSERT(! detail::singleton_wrapper< T >::m_is_destroyed); Chris@16: use(instance); Chris@16: return static_cast(t); Chris@16: } Chris@16: public: Chris@16: BOOST_DLLEXPORT static T & get_mutable_instance(){ Chris@16: BOOST_ASSERT(! is_locked()); Chris@16: return get_instance(); Chris@16: } Chris@16: BOOST_DLLEXPORT static const T & get_const_instance(){ Chris@16: return get_instance(); Chris@16: } Chris@16: BOOST_DLLEXPORT static bool is_destroyed(){ Chris@16: return detail::singleton_wrapper< T >::m_is_destroyed; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: BOOST_DLLEXPORT T & singleton< T >::instance = singleton< T >::get_instance(); Chris@16: Chris@16: } // namespace serialization Chris@16: } // namespace boost Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #endif // BOOST_SERIALIZATION_SINGLETON_HPP