153 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			153 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | #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> | ||
|  | 
 | ||
|  | #include <boost/archive/detail/auto_link_archive.hpp> | ||
|  | #include <boost/serialization/config.hpp> | ||
|  | #include <boost/archive/detail/abi_prefix.hpp> // must be the last header | ||
|  | 
 | ||
|  | #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 BOOST_SYMBOL_VISIBLE singleton_module : | ||
|  |     public boost::noncopyable | ||
|  | { | ||
|  | private: | ||
|  |     static bool & get_lock(); | ||
|  | public: | ||
|  |     BOOST_SERIALIZATION_DECL static void lock(); | ||
|  |     BOOST_SERIALIZATION_DECL static void unlock(); | ||
|  |     BOOST_SERIALIZATION_DECL static bool is_locked(); | ||
|  | }; | ||
|  | 
 | ||
|  | #include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas | ||
|  | 
 | ||
|  | 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 |