Back to home page

EIC code displayed by LXR

 
 

    


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