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