2014-11-19 00:25:21 +08:00
|
|
|
|
#pragma once
|
2017-06-02 14:47:24 +08:00
|
|
|
|
#include "../acl_cpp_define.hpp"
|
2014-11-19 00:25:21 +08:00
|
|
|
|
#include <assert.h>
|
2017-06-02 14:47:24 +08:00
|
|
|
|
#include "noncopyable.hpp"
|
2014-11-19 00:25:21 +08:00
|
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
|
|
|
|
|
namespace acl {
|
|
|
|
|
|
2015-06-29 17:33:11 +08:00
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
2014-11-19 00:25:21 +08:00
|
|
|
|
# pragma warning(push)
|
|
|
|
|
# pragma warning(disable : 4511 4512)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
// 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 noncopyable
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
static void lock()
|
|
|
|
|
{
|
|
|
|
|
get_lock() = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void unlock()
|
|
|
|
|
{
|
|
|
|
|
get_lock() = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool is_locked() {
|
|
|
|
|
return get_lock();
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
static bool& get_lock()
|
|
|
|
|
{
|
|
|
|
|
static bool lock_ = false;
|
|
|
|
|
return lock_;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
class singleton_wrapper : public T
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
static bool destroyed_;
|
|
|
|
|
~singleton_wrapper()
|
|
|
|
|
{
|
|
|
|
|
destroyed_ = true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
bool singleton_wrapper< T >::destroyed_ = false;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD>VC2010<EFBFBD><EFBFBD>GCC<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> main <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD>
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰߳<EFBFBD>ȫ<EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VC2003 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> release <EFBFBD>汾ʱ<EFBFBD>Ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD>
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̲߳<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ܱ<EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD>캯<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* main ֮ǰִ<EFBFBD><EFBFBD>.
|
|
|
|
|
* ʹ<EFBFBD>þ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
|
|
|
|
* class singleton_test : public acl::singleton<singlegon_test>
|
|
|
|
|
* {
|
|
|
|
|
* public:
|
|
|
|
|
* singleton_test() {}
|
|
|
|
|
* ~singleton_test() {}
|
|
|
|
|
* singleton_test& init() { return *this; }
|
|
|
|
|
* };
|
|
|
|
|
|
|
|
|
|
* int main()
|
|
|
|
|
* {
|
|
|
|
|
* singleton_test& test = singleton_test::get_instance();
|
|
|
|
|
* test.init();
|
|
|
|
|
* ...
|
|
|
|
|
* return 0;
|
|
|
|
|
* }
|
|
|
|
|
*/
|
|
|
|
|
template <class T>
|
|
|
|
|
class singleton : public singleton_module
|
|
|
|
|
{
|
|
|
|
|
public:
|
2015-02-07 22:55:24 +08:00
|
|
|
|
static T& get_instance()
|
2014-11-19 00:25:21 +08:00
|
|
|
|
{
|
|
|
|
|
static singleton_wrapper< T > t;
|
|
|
|
|
// refer to instance, causing it to be instantiated (and
|
|
|
|
|
// initialized at startup on working compilers)
|
|
|
|
|
assert(!singleton_wrapper< T >::destroyed_);
|
|
|
|
|
use(instance_);
|
|
|
|
|
return static_cast<T &>(t);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-07 22:55:24 +08:00
|
|
|
|
static bool is_destroyed()
|
2014-11-19 00:25:21 +08:00
|
|
|
|
{
|
|
|
|
|
return singleton_wrapper< T >::destroyed_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2015-02-07 22:55:24 +08:00
|
|
|
|
static T& instance_;
|
2014-11-19 00:25:21 +08:00
|
|
|
|
// include this to provoke instantiation at pre-execution time
|
|
|
|
|
static void use(T const &) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
T& singleton< T >::instance_ = singleton< T >::get_instance();
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> VC2003 <EFBFBD><EFBFBD> release <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܱ<EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* <EFBFBD>Ĺ<EFBFBD><EFBFBD>캯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> main ִ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VC2003 <EFBFBD>±<EFBFBD><EFBFBD>뵥<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
* <EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µĵ<EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD>࣬ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
|
|
|
|
* class singleton_test
|
|
|
|
|
* {
|
|
|
|
|
* public:
|
|
|
|
|
* singleton_test() {}
|
|
|
|
|
* ~singleton_test() {}
|
|
|
|
|
* singleton_test& init() { return *this; }
|
|
|
|
|
* };
|
|
|
|
|
|
|
|
|
|
* int main()
|
|
|
|
|
* {
|
|
|
|
|
* singleton_test& test = acl::singleton2<singleton_test>::get_instance();
|
|
|
|
|
* test.init();
|
|
|
|
|
* ...
|
|
|
|
|
* return 0;
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
template <typename T>
|
|
|
|
|
struct singleton2
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
struct object_creator
|
|
|
|
|
{
|
|
|
|
|
object_creator() { singleton2<T>::get_instance(); }
|
|
|
|
|
inline void do_nothing() const {};
|
|
|
|
|
};
|
|
|
|
|
static object_creator create_object;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
typedef T object_type;
|
|
|
|
|
static object_type & get_instance()
|
|
|
|
|
{
|
|
|
|
|
static object_type obj;
|
|
|
|
|
create_object.do_nothing();
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
typename singleton2<T>::object_creator singleton2<T>::create_object;
|
|
|
|
|
|
2015-06-29 17:33:11 +08:00
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
2014-11-19 00:25:21 +08:00
|
|
|
|
#pragma warning(pop)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
} // namespace acl
|