1#ifndef BOOST_SERIALIZATION_SINGLETON_HPP
2#define BOOST_SERIALIZATION_SINGLETON_HPP
3
4/////////1/////////2///////// 3/////////4/////////5/////////6/////////7/////////8
5// singleton.hpp
6//
7// Copyright David Abrahams 2006. Original version
8//
9// Copyright Robert Ramey 2007. Changes made to permit
10// application throughout the serialization library.
11//
12// Copyright Alexander Grund 2018. Corrections to singleton lifetime
13//
14// Distributed under the Boost
15// Software License, Version 1.0. (See accompanying
16// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
17//
18// The intention here is to define a template which will convert
19// any class into a singleton with the following features:
20//
21// a) initialized before first use.
22// b) thread-safe for const access to the class
23// c) non-locking
24//
25// In order to do this,
26// a) Initialize dynamically when used.
27// b) Require that all singletons be initialized before main
28// is called or any entry point into the shared library is invoked.
29// This guarantees no race condition for initialization.
30// In debug mode, we assert that no non-const functions are called
31// after main is invoked.
32//
33
34// MS compatible compilers support #pragma once
35#if defined(_MSC_VER)
36# pragma once
37#endif
38
39#include <boost/assert.hpp>
40#include <boost/config.hpp>
41#include <boost/noncopyable.hpp>
42#include <boost/serialization/force_include.hpp>
43#include <boost/serialization/config.hpp>
44
45#include <boost/archive/detail/auto_link_archive.hpp>
46#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
47
48#ifdef BOOST_MSVC
49# pragma warning(push)
50# pragma warning(disable : 4511 4512)
51#endif
52
53namespace boost {
54namespace serialization {
55
56//////////////////////////////////////////////////////////////////////
57// Provides a dynamically-initialized (singleton) instance of T in a
58// way that avoids LNK1179 on vc6. See http://tinyurl.com/ljdp8 or
59// http://lists.boost.org/Archives/boost/2006/05/105286.php for
60// details.
61//
62
63// Singletons created by this code are guaranteed to be unique
64// within the executable or shared library which creates them.
65// This is sufficient and in fact ideal for the serialization library.
66// The singleton is created when the module is loaded and destroyed
67// when the module is unloaded.
68
69// This base class has two functions.
70
71// First it provides a module handle for each singleton indicating
72// the executable or shared library in which it was created. This
73// turns out to be necessary and sufficient to implement the tables
74// used by serialization library.
75
76// Second, it provides a mechanism to detect when a non-const function
77// is called after initialization.
78
79// Make a singleton to lock/unlock all singletons for alteration.
80// The intent is that all singletons created/used by this code
81// are to be initialized before main is called. A test program
82// can lock all the singletons when main is entered. Thus any
83// attempt to retrieve a mutable instance while locked will
84// generate an assertion if compiled for debug.
85
86// The singleton template can be used in 2 ways:
87// 1 (Recommended): Publicly inherit your type T from singleton<T>,
88// make its ctor protected and access it via T::get_const_instance()
89// 2: Simply access singleton<T> without changing T. Note that this only
90// provides a global instance accessible by singleton<T>::get_const_instance()
91// or singleton<T>::get_mutable_instance() to prevent using multiple instances
92// of T make its ctor protected
93
94// Note on usage of BOOST_DLLEXPORT: These functions are in danger of
95// being eliminated by the optimizer when building an application in
96// release mode. Usage of the macro is meant to signal the compiler/linker
97// to avoid dropping these functions which seem to be unreferenced.
98// This usage is not related to autolinking.
99
100class BOOST_SYMBOL_VISIBLE singleton_module :
101 public boost::noncopyable
102{
103private:
104 BOOST_DLLEXPORT bool & get_lock() BOOST_USED {
105 static bool lock = false;
106 return lock;
107 }
108
109public:
110 BOOST_DLLEXPORT void lock(){
111 get_lock() = true;
112 }
113 BOOST_DLLEXPORT void unlock(){
114 get_lock() = false;
115 }
116 BOOST_DLLEXPORT bool is_locked(){
117 return get_lock();
118 }
119};
120
121static inline singleton_module & get_singleton_module(){
122 static singleton_module m;
123 return m;
124}
125
126namespace detail {
127
128// This is the class actually instantiated and hence the real singleton.
129// So there will only be one instance of this class. This does not hold
130// for singleton<T> as a class derived from singleton<T> could be
131// instantiated multiple times.
132// It also provides a flag `is_destroyed` which returns true, when the
133// class was destructed. It is static and hence accessible even after
134// destruction. This can be used to check, if the singleton is still
135// accessible e.g. in destructors of other singletons.
136template<class T>
137class singleton_wrapper : public T
138{
139 static bool & get_is_destroyed(){
140 // Prefer a static function member to avoid LNK1179.
141 // Note: As this is for a singleton (1 instance only) it must be set
142 // never be reset (to false)!
143 static bool is_destroyed_flag = false;
144 return is_destroyed_flag;
145 }
146public:
147 singleton_wrapper(){
148 BOOST_ASSERT(! is_destroyed());
149 }
150 ~singleton_wrapper(){
151 get_is_destroyed() = true;
152 }
153 static bool is_destroyed(){
154 return get_is_destroyed();
155 }
156};
157
158} // detail
159
160template <class T>
161class singleton {
162private:
163 static T * m_instance;
164 // include this to provoke instantiation at pre-execution time
165 static void use(T const &) {}
166 static T & get_instance() {
167 BOOST_ASSERT(! is_destroyed());
168
169 // use a wrapper so that types T with protected constructors can be used
170 // Using a static function member avoids LNK1179
171 static detail::singleton_wrapper< T > t;
172
173 // note that the following is absolutely essential.
174 // commenting out this statement will cause compilers to fail to
175 // construct the instance at pre-execution time. This would prevent
176 // our usage/implementation of "locking" and introduce uncertainty into
177 // the sequence of object initialization.
178 // Unfortunately, this triggers detectors of undefined behavior
179 // and reports an error. But I've been unable to find a different way
180 // of guaranteeing that the the singleton is created at pre-main time.
181 if (m_instance) use(* m_instance);
182
183 return static_cast<T &>(t);
184 }
185protected:
186 // Do not allow instantiation of a singleton<T>. But we want to allow
187 // `class T: public singleton<T>` so we can't delete this ctor
188 BOOST_DLLEXPORT singleton(){}
189
190public:
191 BOOST_DLLEXPORT static T & get_mutable_instance(){
192 BOOST_ASSERT(! get_singleton_module().is_locked());
193 return get_instance();
194 }
195 BOOST_DLLEXPORT static const T & get_const_instance(){
196 return get_instance();
197 }
198 BOOST_DLLEXPORT static bool is_destroyed(){
199 return detail::singleton_wrapper< T >::is_destroyed();
200 }
201};
202
203// Assigning the instance reference to a static member forces initialization
204// at startup time as described in
205// https://groups.google.com/forum/#!topic/microsoft.public.vc.language/kDVNLnIsfZk
206template<class T>
207T * singleton< T >::m_instance = & singleton< T >::get_instance();
208
209} // namespace serialization
210} // namespace boost
211
212#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
213
214#ifdef BOOST_MSVC
215#pragma warning(pop)
216#endif
217
218#endif // BOOST_SERIALIZATION_SINGLETON_HPP
219

source code of boost/libs/serialization/include/boost/serialization/singleton.hpp