Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / serialization / singleton.hpp
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 // Distributed under the Boost
13 // Software License, Version 1.0. (See accompanying
14 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15 //
16 // The intention here is to define a template which will convert
17 // any class into a singleton with the following features:
18 //
19 // a) initialized before first use.
20 // b) thread-safe for const access to the class
21 // c) non-locking
22 //
23 // In order to do this,
24 // a) Initialize dynamically when used.
25 // b) Require that all singletons be initialized before main
26 // is called or any entry point into the shared library is invoked.
27 // This guarentees no race condition for initialization.
28 // In debug mode, we assert that no non-const functions are called
29 // after main is invoked.
30 //
31
32 // MS compatible compilers support #pragma once
33 #if defined(_MSC_VER)
34 # pragma once
35 #endif 
36
37 #include <boost/assert.hpp>
38 #include <boost/config.hpp>
39 #include <boost/noncopyable.hpp>
40 #include <boost/serialization/force_include.hpp>
41
42 #include <boost/archive/detail/auto_link_archive.hpp>
43 #include <boost/serialization/config.hpp>
44 #include <boost/archive/detail/abi_prefix.hpp> // must be the last header
45
46 #ifdef BOOST_MSVC
47 #  pragma warning(push)
48 #  pragma warning(disable : 4511 4512)
49 #endif
50
51 namespace boost { 
52 namespace serialization { 
53
54 //////////////////////////////////////////////////////////////////////
55 // Provides a dynamically-initialized (singleton) instance of T in a
56 // way that avoids LNK1179 on vc6.  See http://tinyurl.com/ljdp8 or
57 // http://lists.boost.org/Archives/boost/2006/05/105286.php for
58 // details.
59 //
60
61 // singletons created by this code are guarenteed to be unique
62 // within the executable or shared library which creates them.
63 // This is sufficient and in fact ideal for the serialization library.
64 // The singleton is created when the module is loaded and destroyed
65 // when the module is unloaded.
66
67 // This base class has two functions.
68
69 // First it provides a module handle for each singleton indicating
70 // the executable or shared library in which it was created. This
71 // turns out to be necessary and sufficient to implement the tables
72 // used by serialization library.
73
74 // Second, it provides a mechanism to detect when a non-const function
75 // is called after initialization.
76
77 // make a singleton to lock/unlock all singletons for alteration.
78 // The intent is that all singletons created/used by this code
79 // are to be initialized before main is called. A test program
80 // can lock all the singletons when main is entereed.  This any
81 // attempt to retieve a mutable instances while locked will
82 // generate a assertion if compiled for debug.
83
84 class BOOST_SYMBOL_VISIBLE singleton_module :
85     public boost::noncopyable
86 {
87 private:
88     BOOST_SERIALIZATION_DECL static bool & get_lock();
89 public:
90     static void lock(){
91         get_lock() = true;
92     }
93
94     static void unlock(){
95         get_lock() = false;
96     }
97
98     static bool is_locked(){
99         return get_lock();
100     }
101 };
102
103 #include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
104
105 namespace detail {
106
107 template<class T>
108 class singleton_wrapper : public T
109 {
110 public:
111     static bool m_is_destroyed;
112     ~singleton_wrapper(){
113         m_is_destroyed = true;
114     }
115 };
116
117 template<class T>
118 bool detail::singleton_wrapper< T >::m_is_destroyed = false;
119
120 } // detail
121
122 // note usage of BOOST_DLLEXPORT.  These functions are in danger of
123 // being eliminated by the optimizer when building an application in
124 // release mode. Usage of the macro is meant to signal the compiler/linker
125 // to avoid dropping these functions which seem to be unreferenced.
126 // This usage is not related to autolinking.
127
128 template <class T>
129 class singleton : public singleton_module
130 {
131 private:
132     BOOST_DLLEXPORT static T & instance;
133     // include this to provoke instantiation at pre-execution time
134     static void use(T const *) {}
135     BOOST_DLLEXPORT static T & get_instance() {
136         static detail::singleton_wrapper< T > t;
137         // refer to instance, causing it to be instantiated (and
138         // initialized at startup on working compilers)
139         BOOST_ASSERT(! detail::singleton_wrapper< T >::m_is_destroyed);
140         use(& instance);
141         return static_cast<T &>(t);
142     }
143 public:
144     BOOST_DLLEXPORT static T & get_mutable_instance(){
145         BOOST_ASSERT(! is_locked());
146         return get_instance();
147     }
148     BOOST_DLLEXPORT static const T & get_const_instance(){
149         return get_instance();
150     }
151     BOOST_DLLEXPORT static bool is_destroyed(){
152         return detail::singleton_wrapper< T >::m_is_destroyed;
153     }
154 };
155
156 template<class T>
157 BOOST_DLLEXPORT T & singleton< T >::instance = singleton< T >::get_instance();
158
159 } // namespace serialization
160 } // namespace boost
161
162 #ifdef BOOST_MSVC
163 #pragma warning(pop)
164 #endif
165
166 #endif // BOOST_SERIALIZATION_SINGLETON_HPP