singleton.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #ifndef BOOST_SERIALIZATION_SINGLETON_HPP
  2. #define BOOST_SERIALIZATION_SINGLETON_HPP
  3. /////////1/////////2///////// 3/////////4/////////5/////////6/////////7/////////8
  4. // singleton.hpp
  5. //
  6. // Copyright David Abrahams 2006. Original version
  7. //
  8. // Copyright Robert Ramey 2007. Changes made to permit
  9. // application throughout the serialization library.
  10. //
  11. // Distributed under the Boost
  12. // Software License, Version 1.0. (See accompanying
  13. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  14. //
  15. // The intention here is to define a template which will convert
  16. // any class into a singleton with the following features:
  17. //
  18. // a) initialized before first use.
  19. // b) thread-safe for const access to the class
  20. // c) non-locking
  21. //
  22. // In order to do this,
  23. // a) Initialize dynamically when used.
  24. // b) Require that all singletons be initialized before main
  25. // is called or any entry point into the shared library is invoked.
  26. // This guarentees no race condition for initialization.
  27. // In debug mode, we assert that no non-const functions are called
  28. // after main is invoked.
  29. //
  30. // MS compatible compilers support #pragma once
  31. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  32. # pragma once
  33. #endif
  34. #include <cassert>
  35. #include <boost/config.hpp>
  36. #include <boost/noncopyable.hpp>
  37. #include <boost/serialization/force_include.hpp>
  38. #ifdef BOOST_MSVC
  39. # pragma warning(push)
  40. # pragma warning(disable : 4511 4512)
  41. #endif
  42. namespace boost {
  43. namespace serialization {
  44. //////////////////////////////////////////////////////////////////////
  45. // Provides a dynamically-initialized (singleton) instance of T in a
  46. // way that avoids LNK1179 on vc6. See http://tinyurl.com/ljdp8 or
  47. // http://lists.boost.org/Archives/boost/2006/05/105286.php for
  48. // details.
  49. //
  50. // singletons created by this code are guarenteed to be unique
  51. // within the executable or shared library which creates them.
  52. // This is sufficient and in fact ideal for the serialization library.
  53. // The singleton is created when the module is loaded and destroyed
  54. // when the module is unloaded.
  55. // This base class has two functions.
  56. // First it provides a module handle for each singleton indicating
  57. // the executable or shared library in which it was created. This
  58. // turns out to be necessary and sufficient to implement the tables
  59. // used by serialization library.
  60. // Second, it provides a mechanism to detect when a non-const function
  61. // is called after initialization.
  62. // make a singleton to lock/unlock all singletons for alteration.
  63. // The intent is that all singletons created/used by this code
  64. // are to be initialized before main is called. A test program
  65. // can lock all the singletons when main is entereed. This any
  66. // attempt to retieve a mutable instances while locked will
  67. // generate a assertion if compiled for debug.
  68. class singleton_module :
  69. public boost::noncopyable
  70. {
  71. private:
  72. static bool & get_lock(){
  73. static bool lock = false;
  74. return lock;
  75. }
  76. public:
  77. // static const void * get_module_handle(){
  78. // return static_cast<const void *>(get_module_handle);
  79. // }
  80. static void lock(){
  81. get_lock() = true;
  82. }
  83. static void unlock(){
  84. get_lock() = false;
  85. }
  86. static bool is_locked() {
  87. return get_lock();
  88. }
  89. };
  90. namespace detail {
  91. template<class T>
  92. class singleton_wrapper : public T
  93. {
  94. public:
  95. static bool m_is_destroyed;
  96. ~singleton_wrapper(){
  97. m_is_destroyed = true;
  98. }
  99. };
  100. template<class T>
  101. bool detail::singleton_wrapper<T>::m_is_destroyed = false;
  102. } // detail
  103. template <class T>
  104. class singleton : public singleton_module
  105. {
  106. private:
  107. BOOST_DLLEXPORT static T & instance;
  108. // include this to provoke instantiation at pre-execution time
  109. static void use(T const &) {}
  110. BOOST_DLLEXPORT static T & get_instance() {
  111. static detail::singleton_wrapper<T> t;
  112. // refer to instance, causing it to be instantiated (and
  113. // initialized at startup on working compilers)
  114. assert(! detail::singleton_wrapper<T>::m_is_destroyed);
  115. use(instance);
  116. return static_cast<T &>(t);
  117. }
  118. public:
  119. BOOST_DLLEXPORT static T & get_mutable_instance(){
  120. assert(! is_locked());
  121. return get_instance();
  122. }
  123. BOOST_DLLEXPORT static const T & get_const_instance(){
  124. return get_instance();
  125. }
  126. BOOST_DLLEXPORT static bool is_destroyed(){
  127. return detail::singleton_wrapper<T>::m_is_destroyed;
  128. }
  129. };
  130. template<class T>
  131. BOOST_DLLEXPORT T & singleton<T>::instance = singleton<T>::get_instance();
  132. } // namespace serialization
  133. } // namespace boost
  134. #ifdef BOOST_MSVC
  135. #pragma warning(pop)
  136. #endif
  137. #endif // BOOST_SERIALIZATION_SINGLETON_HPP