Coverage Report

Created: 2026-03-31 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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