|
|
|||
File indexing completed on 2025-12-15 10:08:14
0001 #ifndef BOOST_SERIALIZATION_SINGLETON_HPP 0002 #define BOOST_SERIALIZATION_SINGLETON_HPP 0003 0004 /////////1/////////2///////// 3/////////4/////////5/////////6/////////7/////////8 0005 // singleton.hpp 0006 // 0007 // Copyright David Abrahams 2006. Original version 0008 // 0009 // Copyright Robert Ramey 2007. Changes made to permit 0010 // application throughout the serialization library. 0011 // 0012 // Copyright Alexander Grund 2018. Corrections to singleton lifetime 0013 // 0014 // Distributed under the Boost 0015 // Software License, Version 1.0. (See accompanying 0016 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0017 // 0018 // The intention here is to define a template which will convert 0019 // any class into a singleton with the following features: 0020 // 0021 // a) initialized before first use. 0022 // b) thread-safe for const access to the class 0023 // c) non-locking 0024 // 0025 // In order to do this, 0026 // a) Initialize dynamically when used. 0027 // b) Require that all singletons be initialized before main 0028 // is called or any entry point into the shared library is invoked. 0029 // This guarantees no race condition for initialization. 0030 // In debug mode, we assert that no non-const functions are called 0031 // after main is invoked. 0032 // 0033 0034 // MS compatible compilers support #pragma once 0035 #if defined(_MSC_VER) 0036 # pragma once 0037 #endif 0038 0039 #include <boost/assert.hpp> 0040 #include <boost/config.hpp> 0041 #include <boost/noncopyable.hpp> 0042 #include <boost/serialization/force_include.hpp> 0043 #include <boost/serialization/config.hpp> 0044 0045 #include <boost/archive/detail/auto_link_archive.hpp> 0046 #include <boost/archive/detail/abi_prefix.hpp> // must be the last header 0047 0048 #ifdef BOOST_MSVC 0049 # pragma warning(push) 0050 # pragma warning(disable : 4511 4512) 0051 #endif 0052 0053 namespace boost { 0054 namespace serialization { 0055 0056 ////////////////////////////////////////////////////////////////////// 0057 // Provides a dynamically-initialized (singleton) instance of T in a 0058 // way that avoids LNK1179 on vc6. See http://tinyurl.com/ljdp8 or 0059 // http://lists.boost.org/Archives/boost/2006/05/105286.php for 0060 // details. 0061 // 0062 0063 // Singletons created by this code are guaranteed to be unique 0064 // within the executable or shared library which creates them. 0065 // This is sufficient and in fact ideal for the serialization library. 0066 // The singleton is created when the module is loaded and destroyed 0067 // when the module is unloaded. 0068 0069 // This base class has two functions. 0070 0071 // First it provides a module handle for each singleton indicating 0072 // the executable or shared library in which it was created. This 0073 // turns out to be necessary and sufficient to implement the tables 0074 // used by serialization library. 0075 0076 // Second, it provides a mechanism to detect when a non-const function 0077 // is called after initialization. 0078 0079 // Make a singleton to lock/unlock all singletons for alteration. 0080 // The intent is that all singletons created/used by this code 0081 // are to be initialized before main is called. A test program 0082 // can lock all the singletons when main is entered. Thus any 0083 // attempt to retrieve a mutable instance while locked will 0084 // generate an assertion if compiled for debug. 0085 0086 // The singleton template can be used in 2 ways: 0087 // 1 (Recommended): Publicly inherit your type T from singleton<T>, 0088 // make its ctor protected and access it via T::get_const_instance() 0089 // 2: Simply access singleton<T> without changing T. Note that this only 0090 // provides a global instance accessible by singleton<T>::get_const_instance() 0091 // or singleton<T>::get_mutable_instance() to prevent using multiple instances 0092 // of T make its ctor protected 0093 0094 // Note on usage of BOOST_DLLEXPORT: These functions are in danger of 0095 // being eliminated by the optimizer when building an application in 0096 // release mode. Usage of the macro is meant to signal the compiler/linker 0097 // to avoid dropping these functions which seem to be unreferenced. 0098 // This usage is not related to autolinking. 0099 0100 class BOOST_SYMBOL_VISIBLE singleton_module : 0101 public boost::noncopyable 0102 { 0103 private: 0104 BOOST_DLLEXPORT bool & get_lock() BOOST_USED { 0105 static bool lock = false; 0106 return lock; 0107 } 0108 0109 public: 0110 BOOST_DLLEXPORT void lock(){ 0111 get_lock() = true; 0112 } 0113 BOOST_DLLEXPORT void unlock(){ 0114 get_lock() = false; 0115 } 0116 BOOST_DLLEXPORT bool is_locked(){ 0117 return get_lock(); 0118 } 0119 }; 0120 0121 static inline singleton_module & get_singleton_module(){ 0122 static singleton_module m; 0123 return m; 0124 } 0125 0126 namespace detail { 0127 0128 // This is the class actually instantiated and hence the real singleton. 0129 // So there will only be one instance of this class. This does not hold 0130 // for singleton<T> as a class derived from singleton<T> could be 0131 // instantiated multiple times. 0132 // It also provides a flag `is_destroyed` which returns true, when the 0133 // class was destructed. It is static and hence accessible even after 0134 // destruction. This can be used to check, if the singleton is still 0135 // accessible e.g. in destructors of other singletons. 0136 template<class T> 0137 class singleton_wrapper : public T 0138 { 0139 static bool & get_is_destroyed(){ 0140 // Prefer a static function member to avoid LNK1179. 0141 // Note: As this is for a singleton (1 instance only) it must be set 0142 // never be reset (to false)! 0143 static bool is_destroyed_flag = false; 0144 return is_destroyed_flag; 0145 } 0146 public: 0147 singleton_wrapper(){ 0148 BOOST_ASSERT(! is_destroyed()); 0149 } 0150 ~singleton_wrapper(){ 0151 get_is_destroyed() = true; 0152 } 0153 static bool is_destroyed(){ 0154 return get_is_destroyed(); 0155 } 0156 }; 0157 0158 } // detail 0159 0160 template <class T> 0161 class singleton { 0162 private: 0163 static T * m_instance; 0164 // include this to provoke instantiation at pre-execution time 0165 static void use(T const &) {} 0166 static T & get_instance() { 0167 BOOST_ASSERT(! is_destroyed()); 0168 0169 // use a wrapper so that types T with protected constructors can be used 0170 // Using a static function member avoids LNK1179 0171 static detail::singleton_wrapper< T > t; 0172 0173 // note that the following is absolutely essential. 0174 // commenting out this statement will cause compilers to fail to 0175 // construct the instance at pre-execution time. This would prevent 0176 // our usage/implementation of "locking" and introduce uncertainty into 0177 // the sequence of object initialization. 0178 // Unfortunately, this triggers detectors of undefined behavior 0179 // and reports an error. But I've been unable to find a different way 0180 // of guaranteeing that the the singleton is created at pre-main time. 0181 if (m_instance) use(* m_instance); 0182 0183 return static_cast<T &>(t); 0184 } 0185 protected: 0186 // Do not allow instantiation of a singleton<T>. But we want to allow 0187 // `class T: public singleton<T>` so we can't delete this ctor 0188 BOOST_DLLEXPORT singleton(){} 0189 0190 public: 0191 BOOST_DLLEXPORT static T & get_mutable_instance(){ 0192 BOOST_ASSERT(! get_singleton_module().is_locked()); 0193 return get_instance(); 0194 } 0195 BOOST_DLLEXPORT static const T & get_const_instance(){ 0196 return get_instance(); 0197 } 0198 BOOST_DLLEXPORT static bool is_destroyed(){ 0199 return detail::singleton_wrapper< T >::is_destroyed(); 0200 } 0201 }; 0202 0203 // Assigning the instance reference to a static member forces initialization 0204 // at startup time as described in 0205 // https://groups.google.com/forum/#!topic/microsoft.public.vc.language/kDVNLnIsfZk 0206 template<class T> 0207 T * singleton< T >::m_instance = & singleton< T >::get_instance(); 0208 0209 } // namespace serialization 0210 } // namespace boost 0211 0212 #include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas 0213 0214 #ifdef BOOST_MSVC 0215 #pragma warning(pop) 0216 #endif 0217 0218 #endif // BOOST_SERIALIZATION_SINGLETON_HPP
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|