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