singleton.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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)
  32. # pragma once
  33. #endif
  34. #include <boost/assert.hpp>
  35. #include <boost/config.hpp>
  36. #include <boost/noncopyable.hpp>
  37. #include <boost/serialization/force_include.hpp>
  38. #include <boost/archive/detail/auto_link_archive.hpp>
  39. #include <boost/serialization/config.hpp>
  40. #include <boost/archive/detail/abi_prefix.hpp> // must be the last header
  41. #ifdef BOOST_MSVC
  42. # pragma warning(push)
  43. # pragma warning(disable : 4511 4512)
  44. #endif
  45. namespace boost {
  46. namespace serialization {
  47. //////////////////////////////////////////////////////////////////////
  48. // Provides a dynamically-initialized (singleton) instance of T in a
  49. // way that avoids LNK1179 on vc6. See http://tinyurl.com/ljdp8 or
  50. // http://lists.boost.org/Archives/boost/2006/05/105286.php for
  51. // details.
  52. //
  53. // singletons created by this code are guarenteed to be unique
  54. // within the executable or shared library which creates them.
  55. // This is sufficient and in fact ideal for the serialization library.
  56. // The singleton is created when the module is loaded and destroyed
  57. // when the module is unloaded.
  58. // This base class has two functions.
  59. // First it provides a module handle for each singleton indicating
  60. // the executable or shared library in which it was created. This
  61. // turns out to be necessary and sufficient to implement the tables
  62. // used by serialization library.
  63. // Second, it provides a mechanism to detect when a non-const function
  64. // is called after initialization.
  65. // make a singleton to lock/unlock all singletons for alteration.
  66. // The intent is that all singletons created/used by this code
  67. // are to be initialized before main is called. A test program
  68. // can lock all the singletons when main is entereed. This any
  69. // attempt to retieve a mutable instances while locked will
  70. // generate a assertion if compiled for debug.
  71. // note usage of BOOST_DLLEXPORT. These functions are in danger of
  72. // being eliminated by the optimizer when building an application in
  73. // release mode. Usage of the macro is meant to signal the compiler/linker
  74. // to avoid dropping these functions which seem to be unreferenced.
  75. // This usage is not related to autolinking.
  76. class BOOST_SYMBOL_VISIBLE singleton_module :
  77. public boost::noncopyable
  78. {
  79. private:
  80. BOOST_DLLEXPORT static bool & get_lock() BOOST_USED {
  81. static bool lock = false;
  82. return lock;
  83. }
  84. public:
  85. BOOST_DLLEXPORT static void lock(){
  86. get_lock() = true;
  87. }
  88. BOOST_DLLEXPORT static void unlock(){
  89. get_lock() = false;
  90. }
  91. BOOST_DLLEXPORT static bool is_locked(){
  92. return get_lock();
  93. }
  94. };
  95. template <class T>
  96. class singleton : public singleton_module
  97. {
  98. private:
  99. static T & m_instance;
  100. // include this to provoke instantiation at pre-execution time
  101. static void use(T const *) {}
  102. static T & get_instance() {
  103. // use a wrapper so that types T with protected constructors
  104. // can be used
  105. class singleton_wrapper : public T {};
  106. static singleton_wrapper t;
  107. // refer to instance, causing it to be instantiated (and
  108. // initialized at startup on working compilers)
  109. BOOST_ASSERT(! is_destroyed());
  110. // note that the following is absolutely essential.
  111. // commenting out this statement will cause compilers to fail to
  112. // construct the instance at pre-execution time. This would prevent
  113. // our usage/implementation of "locking" and introduce uncertainty into
  114. // the sequence of object initializaition.
  115. use(& m_instance);
  116. return static_cast<T &>(t);
  117. }
  118. static bool & get_is_destroyed(){
  119. static bool is_destroyed;
  120. return is_destroyed;
  121. }
  122. public:
  123. BOOST_DLLEXPORT static T & get_mutable_instance(){
  124. BOOST_ASSERT(! is_locked());
  125. return get_instance();
  126. }
  127. BOOST_DLLEXPORT static const T & get_const_instance(){
  128. return get_instance();
  129. }
  130. BOOST_DLLEXPORT static bool is_destroyed(){
  131. return get_is_destroyed();
  132. }
  133. BOOST_DLLEXPORT singleton(){
  134. get_is_destroyed() = false;
  135. }
  136. BOOST_DLLEXPORT ~singleton() {
  137. get_is_destroyed() = true;
  138. }
  139. };
  140. template<class T>
  141. T & singleton< T >::m_instance = singleton< T >::get_instance();
  142. } // namespace serialization
  143. } // namespace boost
  144. #include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
  145. #ifdef BOOST_MSVC
  146. #pragma warning(pop)
  147. #endif
  148. #endif // BOOST_SERIALIZATION_SINGLETON_HPP