| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 | #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.//// Copyright Alexander Grund 2018. Corrections to singleton lifetime//// 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/serialization/config.hpp>#include <boost/archive/detail/auto_link_archive.hpp>#include <boost/archive/detail/abi_prefix.hpp> // must be the last header#ifdef BOOST_MSVC#  pragma warning(push)#  pragma warning(disable : 4511 4512)#endifnamespace 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 guaranteed 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 entered.  Thus any// attempt to retrieve a mutable instance while locked will// generate an assertion if compiled for debug.// The singleton template can be used in 2 ways:// 1 (Recommended): Publicly inherit your type T from singleton<T>,// make its ctor protected and access it via T::get_const_instance()// 2: Simply access singleton<T> without changing T. Note that this only// provides a global instance accesible by singleton<T>::get_const_instance()// or singleton<T>::get_mutable_instance() to prevent using multiple instances// of T make its ctor protected// Note on usage of BOOST_DLLEXPORT: These functions are in danger of// being eliminated by the optimizer when building an application in// release mode. Usage of the macro is meant to signal the compiler/linker// to avoid dropping these functions which seem to be unreferenced.// This usage is not related to autolinking.class BOOST_SYMBOL_VISIBLE singleton_module :    public boost::noncopyable{private:    BOOST_DLLEXPORT bool & get_lock() BOOST_USED {        static bool lock = false;        return lock;    }public:    BOOST_DLLEXPORT void lock(){        get_lock() = true;    }    BOOST_DLLEXPORT void unlock(){        get_lock() = false;    }    BOOST_DLLEXPORT bool is_locked(){        return get_lock();    }};static inline singleton_module & get_singleton_module(){    static singleton_module m;    return m;}namespace detail {// This is the class actually instantiated and hence the real singleton.// So there will only be one instance of this class. This does not hold// for singleton<T> as a class derived from singleton<T> could be// instantiated multiple times.// It also provides a flag `is_destroyed` which returns true, when the// class was destructed. It is static and hence accesible even after// destruction. This can be used to check, if the singleton is still// accesible e.g. in destructors of other singletons.template<class T>class singleton_wrapper : public T{    static bool & get_is_destroyed(){        // Prefer a static function member to avoid LNK1179.        // Note: As this is for a singleton (1 instance only) it must be set        // never be reset (to false)!        static bool is_destroyed_flag = false;        return is_destroyed_flag;    }public:    singleton_wrapper(){        BOOST_ASSERT(! is_destroyed());    }    ~singleton_wrapper(){        get_is_destroyed() = true;    }    static bool is_destroyed(){        return get_is_destroyed();    }};} // detailtemplate <class T>class singleton {private:    static T * m_instance;    // include this to provoke instantiation at pre-execution time    static void use(T const &) {}    static T & get_instance() {        BOOST_ASSERT(! is_destroyed());        // use a wrapper so that types T with protected constructors can be used        // Using a static function member avoids LNK1179        static detail::singleton_wrapper< T > t;        // note that the following is absolutely essential.        // commenting out this statement will cause compilers to fail to        // construct the instance at pre-execution time.  This would prevent        // our usage/implementation of "locking" and introduce uncertainty into        // the sequence of object initialization.        // Unfortunately, this triggers detectors of undefine behavior        // and reports an error.  But I've been unable to find a different        // of guarenteeing that the the singleton is created at pre-main time.        if (m_instance) use(* m_instance);        return static_cast<T &>(t);    }protected:    // Do not allow instantiation of a singleton<T>. But we want to allow    // `class T: public singleton<T>` so we can't delete this ctor    BOOST_DLLEXPORT singleton(){}public:    BOOST_DLLEXPORT static T & get_mutable_instance(){        BOOST_ASSERT(! get_singleton_module().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 >::is_destroyed();    }};// Assigning the instance reference to a static member forces initialization// at startup time as described in// https://groups.google.com/forum/#!topic/microsoft.public.vc.language/kDVNLnIsfZktemplate<class T>T * singleton< T >::m_instance = & singleton< T >::get_instance();} // namespace serialization} // namespace boost#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas#ifdef BOOST_MSVC#pragma warning(pop)#endif#endif // BOOST_SERIALIZATION_SINGLETON_HPP
 |