#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) && (_MSC_VER >= 1020) | |
# 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 |