Brian Silverman | 8867871 | 2018-08-04 23:56:48 -0700 | [diff] [blame^] | 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> |