]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
2 | <html> | |
3 | <!-- | |
4 | (C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com . | |
5 | Use, modification and distribution is subject to the Boost Software | |
6 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
7 | http://www.boost.org/LICENSE_1_0.txt) | |
8 | --> | |
9 | <head> | |
10 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | |
11 | <link rel="stylesheet" type="text/css" href="../../../boost.css"> | |
12 | <link rel="stylesheet" type="text/css" href="style.css"> | |
13 | <title>Serialization - singleton</title> | |
14 | </head> | |
15 | <body link="#0000ff" vlink="#800080"> | |
16 | <table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header"> | |
17 | <tr> | |
18 | <td valign="top" width="300"> | |
19 | <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../boost.png" border="0"></a></h3> | |
20 | </td> | |
21 | <td valign="top"> | |
22 | <h1 align="center">Serialization</h1> | |
23 | <h2 align="center"><code style="white-space: normal">singleton</code></h2> | |
24 | </td> | |
25 | </tr> | |
26 | </table> | |
27 | <hr> | |
28 | <dl class="page-index"> | |
29 | <dt><a href="#motivation">Motivation</a> | |
30 | <dt><a href="#features">Features</a> | |
31 | <dt><a href="#classinterface">Class Interface</a> | |
32 | <dt><a href="#requirements">Requirements</a> | |
33 | <dt><a href="#example">Examples</a> | |
34 | <dt><a href="#multithreading">Multi-Threading</a> | |
35 | </dl> | |
36 | ||
37 | <h3><a name="motivation">Motivation</a></h3> | |
38 | The serialization library relies on the existence of a number | |
39 | of static variables and tables to store information related | |
40 | to runtime types. Examples are tables which relate exported | |
41 | names to types and tables which relate base classes to derived | |
42 | classes. Construction, destruction and usage of these variables | |
43 | requires consideration of the following issues: | |
44 | <ul> | |
45 | <li>Some static data variable and constant entries refer to others. | |
46 | The sequence of initialization cannot be arbitrary but must be in proper | |
47 | sequence.</li> | |
48 | <li>A number of static variables aren't referred to explicitly and, without | |
49 | special precautions, will be stripped by most code optimizers</li> | |
50 | <li>Many of these variables are created by templates and special care must | |
51 | be taken to be sure that they are instantiated</li> | |
52 | <li>In a multi-threading system, its possible that these static variables | |
53 | will be accessed concurrently by separate threads. This would create a | |
54 | race condition with unpredictabe behavior</li> | |
55 | </ul> | |
56 | This singleton class addresses all of the above issues. | |
57 | ||
58 | <h3><a name="features">Features</a></h3> | |
59 | This singleton implementation has the following features: | |
60 | <ul> | |
61 | <li> | |
62 | Any instance will be constructed before any attempt is made to access it.</li> | |
63 | <li> | |
64 | Any instance created with a template is guaranteed to be instantiated. | |
65 | <li> | |
66 | Regardless of whether or not an instance has been explicitly | |
67 | referred to, it will not be stripped by the optimizer when the | |
68 | executable is built in release mode. | |
69 | <li> | |
70 | All instances are constructed before | |
71 | <code style="white-space: normal">main</code> is called | |
72 | regardless of where they might be referenced within the program. | |
73 | In a multi-tasking system, this guarantees that there will be no | |
74 | race conditions during the construction of any instance. No | |
75 | thread locking is required to guarantee this. | |
76 | <li> | |
77 | The above implies that any <code style="white-space: normal">const</code> | |
78 | instances are thread-safe during the whole program. Again, no | |
79 | thread locking is required. | |
80 | <li> | |
81 | If a mutable instance is created, and such an instance is modified | |
82 | after main is called in a multi-threading system, there exists | |
83 | the possibility that a race condition will occur. The serialization | |
84 | library takes care that in the few places where a mutable | |
85 | singleton is required, it is not altered after | |
86 | <code style="white-space: normal">main</code> is called. | |
87 | For a more general purpose usage, thread locking on this | |
88 | singleton could easily be implemented. But as the serialization | |
89 | library didn't require it, it wasn't implemented. | |
90 | </ul> | |
91 | ||
92 | <h3><a name="classinterface">Class Interface</a></h3> | |
93 | <pre><code> | |
94 | namespace boost { | |
95 | namespace serialization { | |
96 | ||
97 | template <class T> | |
98 | class singleton : public boost::noncopyable | |
99 | { | |
100 | public: | |
101 | static const T & get_const_instance(); | |
102 | static T & get_mutable_instance(); | |
103 | static bool is_destroyed(); | |
104 | }; | |
105 | ||
106 | } // namespace serialization | |
107 | } // namespace boost | |
108 | </code></pre> | |
109 | ||
110 | <dl> | |
111 | ||
112 | <dt><h4><pre><code> | |
113 | static const T & get_const_instance(); | |
114 | </code></pre></h4></dt> | |
115 | <dd> | |
116 | Retrieve a constant reference to the singleton for this type. | |
117 | </dd> | |
118 | ||
119 | <dt><h4><pre><code> | |
120 | static T & get_mutable_instance(); | |
121 | </code></pre></h4></dt> | |
122 | <dd> | |
123 | Retrieve a mutable reference to the singleton for this type. | |
124 | </dd> | |
125 | ||
126 | <dt><h4><pre><code> | |
127 | static bool is_destroyed(); | |
128 | </code></pre></h4></dt> | |
129 | <dd> | |
130 | Return <code>true</code> if the destructor on this singleton has been | |
131 | called. Otherwise, return <code>false</code>. | |
132 | </dd> | |
133 | ||
134 | </dl> | |
135 | ||
136 | <h3><a name="requirements">Requirements</a></h3> | |
137 | In order to be used as | |
138 | <a target="singleton.hpp" href = "../../../boost/serialization/singleton.hpp"> | |
139 | <code style="white-space: normal"> | |
140 | singleton<T> | |
141 | </code> | |
142 | </a>, the type T must be default constructable. | |
143 | It doesn't require static variables - though it may have them. | |
144 | Since the library guarantees that only one instance of | |
145 | <a target="singleton.hpp" href = "../../../boost/serialization/singleton.hpp"> | |
146 | <code style="white-space: normal"> | |
147 | singleton<T> | |
148 | </code> | |
149 | </a> | |
150 | exists and all accesss is through the above static interface | |
151 | functions, common member functions of T become | |
152 | the functional equivalent of | |
153 | <code style="white-space: normal">static</code> functions. | |
154 | ||
155 | <h3><a name="example">Examples</a></h3> | |
156 | There are at least two different ways to use this class template. | |
157 | Both are used in the serialization library. | |
158 | <p> | |
159 | The first way is illustrated by an excerpt from the file | |
160 | <code style="white-space: normal"><a target="extended_type_info" href="../src/extended_type_info.cpp">extended_type_info.cpp</a></code>. | |
161 | which contains the following code: | |
162 | ||
163 | <pre><code> | |
164 | typedef std::set<const extended_type_info *, key_compare> ktmap; | |
165 | ... | |
166 | void | |
167 | extended_type_info::key_register(const char *key) { | |
168 | ... | |
169 | result = singleton<ktmap>::get_mutable_instance().insert(this); | |
170 | ... | |
171 | } | |
172 | </code></pre> | |
173 | Just by referring to the singleton instance anywhere in the program | |
174 | will guarantee that one and only one instance for the specified | |
175 | type (<code style="white-space: normal">ktmap</code> in this example) | |
176 | will exist throughout the program. There is no need for any other | |
177 | declaration or definition. | |
178 | <p> | |
179 | A second way is to use | |
180 | <a target="singleton.hpp" href = "../../../boost/serialization/singleton.hpp"> | |
181 | <code style="white-space: normal"> | |
182 | singleton<T> | |
183 | </code> | |
184 | </a> | |
185 | as one of the base classes of the type. This is illustrated by a simplified | |
186 | excerpt from | |
187 | <a target="extended_type_info_typeid.hpp" href = "../../../boost/serialization/extended_type_info_typeid.hpp"> | |
188 | <code style="white-space: normal"> | |
189 | extended_type_info_typeid.hpp | |
190 | </code> | |
191 | </a> | |
192 | ||
193 | <pre><code> | |
194 | template<class T> | |
195 | class extended_type_info_typeid : | |
196 | public detail::extended_type_info_typeid_0, | |
197 | public singleton<extended_type_info_typeid<const T> > | |
198 | { | |
199 | friend class singleton<extended_type_info_typeid<const T> >; | |
200 | private: | |
201 | // private constructor to inhibit any existence other than the | |
202 | // static one. Note: not all compilers support this !!! | |
203 | extended_type_info_typeid() : | |
204 | detail::extended_type_info_typeid_0() | |
205 | { | |
206 | type_register(typeid(T)); | |
207 | } | |
208 | ~extended_type_info_typeid(){} | |
209 | ... | |
210 | }; | |
211 | </code></pre> | |
212 | ||
213 | This usage will permit a more natural syntax to be used: | |
214 | <pre><code> | |
215 | extended_type_info_typeid<T>::get_const_instance() | |
216 | </code></pre> | |
217 | ||
218 | Again, including one or more of the above statements anywhere | |
219 | in the program will guarantee that one and only one instance | |
220 | is created and referred to. | |
221 | ||
222 | <h3><a name="multithreading">Multi-Threading</a></h3> | |
223 | This singleton CAN be safely used in multi-threading applications if one | |
224 | is careful follow a simple rule: | |
225 | <p> | |
226 | <b>Do not call get_mutable_instance when more than one thread is running!</b> | |
227 | All singletons used in the serialization library follow this rule. | |
228 | In order to help detect accidental violations of this rule there | |
229 | exist singleton lock/unlock functions. | |
230 | <pre><code> | |
231 | void boost::serialization::singleton_module::lock(); | |
232 | void boost::serialization::singleton_module::unlock(); | |
233 | bool boost::serialization::singleton_module::is_locked(); | |
234 | </code></pre> | |
235 | In a program compiled for debug, any invocation of | |
236 | <code style="white-space: normal">get_mutable_instance()</code> | |
237 | while the library is in a "locked" state will trap in an assertion. | |
238 | The singleton module lock state is initialized as "unlocked" to permit | |
239 | alteration of static variables before | |
240 | <code style="white-space: normal">main</code> is called. | |
241 | The <code style="white-space: normal">lock()</code> and | |
242 | <code style="white-space: normal">unlock()</code> are "global" | |
243 | in that they affect ALL the singletons defined by this template. | |
244 | All serialization tests invoke <code style="white-space: normal">lock()</code> | |
245 | at the start of the progam. For programs compiled in release | |
246 | mode these functions have no effect. | |
247 | ||
248 | <hr> | |
249 | <p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2007. | |
250 | Distributed under the Boost Software License, Version 1.0. (See | |
251 | accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
252 | </i></p> | |
253 | </body> | |
254 | </html> |