/src/boost_1_84_0/boost/serialization/singleton.hpp
Line | Count | Source |
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 | | |
53 | | namespace boost { |
54 | | namespace 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 | | |
100 | | class BOOST_SYMBOL_VISIBLE singleton_module : |
101 | | public boost::noncopyable |
102 | | { |
103 | | private: |
104 | 0 | BOOST_DLLEXPORT bool & get_lock() BOOST_USED { |
105 | 0 | static bool lock = false; |
106 | 0 | return lock; |
107 | 0 | } |
108 | | |
109 | | public: |
110 | 0 | BOOST_DLLEXPORT void lock(){ |
111 | 0 | get_lock() = true; |
112 | 0 | } |
113 | 0 | BOOST_DLLEXPORT void unlock(){ |
114 | 0 | get_lock() = false; |
115 | 0 | } |
116 | 0 | BOOST_DLLEXPORT bool is_locked(){ |
117 | 0 | return get_lock(); |
118 | 0 | } |
119 | | }; |
120 | | |
121 | 0 | static inline singleton_module & get_singleton_module(){ |
122 | 0 | static singleton_module m; |
123 | 0 | return m; |
124 | 0 | } Unexecuted instantiation: extended_type_info.cpp:boost::serialization::get_singleton_module() Unexecuted instantiation: text_iarchive.cpp:boost::serialization::get_singleton_module() Unexecuted instantiation: text_oarchive.cpp:boost::serialization::get_singleton_module() |
125 | | |
126 | | namespace 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. |
136 | | template<class T> |
137 | | class singleton_wrapper : public T |
138 | | { |
139 | 0 | 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 | 0 | static bool is_destroyed_flag = false; |
144 | 0 | return is_destroyed_flag; |
145 | 0 | } Unexecuted instantiation: boost::serialization::detail::singleton_wrapper<std::__1::multiset<boost::serialization::extended_type_info const*, boost::serialization::detail::key_compare, std::__1::allocator<boost::serialization::extended_type_info const*> > >::get_is_destroyed() Unexecuted instantiation: boost::serialization::detail::singleton_wrapper<boost::archive::detail::extra_detail::map<boost::archive::text_iarchive> >::get_is_destroyed() Unexecuted instantiation: boost::serialization::detail::singleton_wrapper<boost::archive::detail::extra_detail::map<boost::archive::text_oarchive> >::get_is_destroyed() |
146 | | public: |
147 | 18 | singleton_wrapper(){ |
148 | 18 | BOOST_ASSERT(! is_destroyed()); |
149 | 18 | } boost::serialization::detail::singleton_wrapper<std::__1::multiset<boost::serialization::extended_type_info const*, boost::serialization::detail::key_compare, std::__1::allocator<boost::serialization::extended_type_info const*> > >::singleton_wrapper() Line | Count | Source | 147 | 6 | singleton_wrapper(){ | 148 | | BOOST_ASSERT(! is_destroyed()); | 149 | 6 | } |
boost::serialization::detail::singleton_wrapper<boost::archive::detail::extra_detail::map<boost::archive::text_iarchive> >::singleton_wrapper() Line | Count | Source | 147 | 6 | singleton_wrapper(){ | 148 | | BOOST_ASSERT(! is_destroyed()); | 149 | 6 | } |
boost::serialization::detail::singleton_wrapper<boost::archive::detail::extra_detail::map<boost::archive::text_oarchive> >::singleton_wrapper() Line | Count | Source | 147 | 6 | singleton_wrapper(){ | 148 | | BOOST_ASSERT(! is_destroyed()); | 149 | 6 | } |
|
150 | 0 | ~singleton_wrapper(){ |
151 | 0 | get_is_destroyed() = true; |
152 | 0 | } Unexecuted instantiation: boost::serialization::detail::singleton_wrapper<std::__1::multiset<boost::serialization::extended_type_info const*, boost::serialization::detail::key_compare, std::__1::allocator<boost::serialization::extended_type_info const*> > >::~singleton_wrapper() Unexecuted instantiation: boost::serialization::detail::singleton_wrapper<boost::archive::detail::extra_detail::map<boost::archive::text_iarchive> >::~singleton_wrapper() Unexecuted instantiation: boost::serialization::detail::singleton_wrapper<boost::archive::detail::extra_detail::map<boost::archive::text_oarchive> >::~singleton_wrapper() |
153 | 0 | static bool is_destroyed(){ |
154 | 0 | return get_is_destroyed(); |
155 | 0 | } Unexecuted instantiation: boost::serialization::detail::singleton_wrapper<std::__1::multiset<boost::serialization::extended_type_info const*, boost::serialization::detail::key_compare, std::__1::allocator<boost::serialization::extended_type_info const*> > >::is_destroyed() Unexecuted instantiation: boost::serialization::detail::singleton_wrapper<boost::archive::detail::extra_detail::map<boost::archive::text_iarchive> >::is_destroyed() Unexecuted instantiation: boost::serialization::detail::singleton_wrapper<boost::archive::detail::extra_detail::map<boost::archive::text_oarchive> >::is_destroyed() |
156 | | }; |
157 | | |
158 | | } // detail |
159 | | |
160 | | template <class T> |
161 | | class singleton { |
162 | | private: |
163 | | static T * m_instance; |
164 | | // include this to provoke instantiation at pre-execution time |
165 | 0 | static void use(T const &) {}Unexecuted instantiation: boost::serialization::singleton<std::__1::multiset<boost::serialization::extended_type_info const*, boost::serialization::detail::key_compare, std::__1::allocator<boost::serialization::extended_type_info const*> > >::use(std::__1::multiset<boost::serialization::extended_type_info const*, boost::serialization::detail::key_compare, std::__1::allocator<boost::serialization::extended_type_info const*> > const&) Unexecuted instantiation: boost::serialization::singleton<boost::archive::detail::extra_detail::map<boost::archive::text_iarchive> >::use(boost::archive::detail::extra_detail::map<boost::archive::text_iarchive> const&) Unexecuted instantiation: boost::serialization::singleton<boost::archive::detail::extra_detail::map<boost::archive::text_oarchive> >::use(boost::archive::detail::extra_detail::map<boost::archive::text_oarchive> const&) |
166 | 18 | static T & get_instance() { |
167 | 18 | 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 | 18 | 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 | 18 | if (m_instance) use(* m_instance); |
182 | | |
183 | 18 | return static_cast<T &>(t); |
184 | 18 | } boost::serialization::singleton<std::__1::multiset<boost::serialization::extended_type_info const*, boost::serialization::detail::key_compare, std::__1::allocator<boost::serialization::extended_type_info const*> > >::get_instance() Line | Count | Source | 166 | 6 | static T & get_instance() { | 167 | 6 | 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 | 6 | 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 | 6 | if (m_instance) use(* m_instance); | 182 | | | 183 | 6 | return static_cast<T &>(t); | 184 | 6 | } |
boost::serialization::singleton<boost::archive::detail::extra_detail::map<boost::archive::text_iarchive> >::get_instance() Line | Count | Source | 166 | 6 | static T & get_instance() { | 167 | 6 | 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 | 6 | 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 | 6 | if (m_instance) use(* m_instance); | 182 | | | 183 | 6 | return static_cast<T &>(t); | 184 | 6 | } |
boost::serialization::singleton<boost::archive::detail::extra_detail::map<boost::archive::text_oarchive> >::get_instance() Line | Count | Source | 166 | 6 | static T & get_instance() { | 167 | 6 | 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 | 6 | 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 | 6 | if (m_instance) use(* m_instance); | 182 | | | 183 | 6 | return static_cast<T &>(t); | 184 | 6 | } |
|
185 | | protected: |
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 | | |
190 | | public: |
191 | 0 | BOOST_DLLEXPORT static T & get_mutable_instance(){ |
192 | 0 | BOOST_ASSERT(! get_singleton_module().is_locked()); |
193 | 0 | return get_instance(); |
194 | 0 | } Unexecuted instantiation: boost::serialization::singleton<std::__1::multiset<boost::serialization::extended_type_info const*, boost::serialization::detail::key_compare, std::__1::allocator<boost::serialization::extended_type_info const*> > >::get_mutable_instance() Unexecuted instantiation: boost::serialization::singleton<boost::archive::detail::extra_detail::map<boost::archive::text_iarchive> >::get_mutable_instance() Unexecuted instantiation: boost::serialization::singleton<boost::archive::detail::extra_detail::map<boost::archive::text_oarchive> >::get_mutable_instance() |
195 | 0 | BOOST_DLLEXPORT static const T & get_const_instance(){ |
196 | 0 | return get_instance(); |
197 | 0 | } Unexecuted instantiation: boost::serialization::singleton<std::__1::multiset<boost::serialization::extended_type_info const*, boost::serialization::detail::key_compare, std::__1::allocator<boost::serialization::extended_type_info const*> > >::get_const_instance() Unexecuted instantiation: boost::serialization::singleton<boost::archive::detail::extra_detail::map<boost::archive::text_iarchive> >::get_const_instance() Unexecuted instantiation: boost::serialization::singleton<boost::archive::detail::extra_detail::map<boost::archive::text_oarchive> >::get_const_instance() |
198 | 0 | BOOST_DLLEXPORT static bool is_destroyed(){ |
199 | 0 | return detail::singleton_wrapper< T >::is_destroyed(); |
200 | 0 | } Unexecuted instantiation: boost::serialization::singleton<std::__1::multiset<boost::serialization::extended_type_info const*, boost::serialization::detail::key_compare, std::__1::allocator<boost::serialization::extended_type_info const*> > >::is_destroyed() Unexecuted instantiation: boost::serialization::singleton<boost::archive::detail::extra_detail::map<boost::archive::text_iarchive> >::is_destroyed() Unexecuted instantiation: boost::serialization::singleton<boost::archive::detail::extra_detail::map<boost::archive::text_oarchive> >::is_destroyed() |
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 |
206 | | template<class T> |
207 | | T * 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 |