xref: /aoo42x/main/sal/inc/rtl/instance.hxx (revision 86e1cf34)
1565d668cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3565d668cSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4565d668cSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5565d668cSAndrew Rist  * distributed with this work for additional information
6565d668cSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7565d668cSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8565d668cSAndrew Rist  * "License"); you may not use this file except in compliance
9565d668cSAndrew Rist  * with the License.  You may obtain a copy of the License at
10565d668cSAndrew Rist  *
11565d668cSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12565d668cSAndrew Rist  *
13565d668cSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14565d668cSAndrew Rist  * software distributed under the License is distributed on an
15565d668cSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16565d668cSAndrew Rist  * KIND, either express or implied.  See the License for the
17565d668cSAndrew Rist  * specific language governing permissions and limitations
18565d668cSAndrew Rist  * under the License.
19565d668cSAndrew Rist  *
20565d668cSAndrew Rist  *************************************************************/
21565d668cSAndrew Rist 
22565d668cSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #if !defined INCLUDED_RTL_INSTANCE_HXX
25cdf0e10cSrcweir #define INCLUDED_RTL_INSTANCE_HXX
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "osl/doublecheckedlocking.h"
28cdf0e10cSrcweir #include "osl/getglobalmutex.hxx"
29cdf0e10cSrcweir 
30cdf0e10cSrcweir namespace {
31cdf0e10cSrcweir 
32cdf0e10cSrcweir /** A non-broken version of the double-checked locking pattern.
33cdf0e10cSrcweir 
34cdf0e10cSrcweir     See
35cdf0e10cSrcweir     <http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html>
36cdf0e10cSrcweir     for a description of double-checked locking, why it is broken, and how it
37cdf0e10cSrcweir     can be fixed.  Always use this template instead of spelling out the
38cdf0e10cSrcweir     double-checked locking pattern explicitly, and only in those rare cases
39cdf0e10cSrcweir     where that is not possible and you have to spell it out explicitly, at
40cdf0e10cSrcweir     least call OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER() at the right
41cdf0e10cSrcweir     places.  That way, all platform-dependent code to make double-checked
42cdf0e10cSrcweir     locking work can be kept in one place.
43cdf0e10cSrcweir 
44cdf0e10cSrcweir     Usage scenarios:
45cdf0e10cSrcweir 
46cdf0e10cSrcweir     1  Static instance (most common case)
47cdf0e10cSrcweir 
48cdf0e10cSrcweir     Pattern:
49cdf0e10cSrcweir 
50cdf0e10cSrcweir       T * getInstance()
51cdf0e10cSrcweir       {
52cdf0e10cSrcweir           static T * pInstance = 0;
53cdf0e10cSrcweir           if (!pInstance)
54cdf0e10cSrcweir           {
55cdf0e10cSrcweir               ::osl::MutexGuard aGuard(::osl::Mutex::getGlobalMutex());
56cdf0e10cSrcweir               if (!pInstance)
57cdf0e10cSrcweir               {
58cdf0e10cSrcweir                   static T aInstance;
59cdf0e10cSrcweir                   pInstance = &aInstance;
60cdf0e10cSrcweir               }
61cdf0e10cSrcweir           }
62cdf0e10cSrcweir           return pInstance;
63cdf0e10cSrcweir       }
64cdf0e10cSrcweir 
65cdf0e10cSrcweir     Code:
66cdf0e10cSrcweir 
67cdf0e10cSrcweir       #include "rtl/instance.hxx"
68cdf0e10cSrcweir       #include "osl/getglobalmutex.hxx"
69cdf0e10cSrcweir 
70cdf0e10cSrcweir       namespace {
71cdf0e10cSrcweir           struct Init
72cdf0e10cSrcweir           {
73cdf0e10cSrcweir               T * operator()()
74cdf0e10cSrcweir               {
75cdf0e10cSrcweir                   static T aInstance;
76cdf0e10cSrcweir                   return &aInstance;
77cdf0e10cSrcweir               }
78cdf0e10cSrcweir           };
79cdf0e10cSrcweir       }
80cdf0e10cSrcweir 
81cdf0e10cSrcweir       T * getInstance()
82cdf0e10cSrcweir       {
83cdf0e10cSrcweir           return rtl_Instance< T, Init, ::osl::MutexGuard,
84cdf0e10cSrcweir                                ::osl::GetGlobalMutex >::create(
85cdf0e10cSrcweir               Init(), ::osl::GetGlobalMutex());
86cdf0e10cSrcweir       }
87cdf0e10cSrcweir 
88cdf0e10cSrcweir     2  Dynamic instance
89cdf0e10cSrcweir 
90cdf0e10cSrcweir     Pattern:
91cdf0e10cSrcweir 
92cdf0e10cSrcweir       T * getInstance()
93cdf0e10cSrcweir       {
94cdf0e10cSrcweir           static T * pInstance = 0;
95cdf0e10cSrcweir           if (!pInstance)
96cdf0e10cSrcweir           {
97cdf0e10cSrcweir               ::osl::MutexGuard aGuard(::osl::Mutex::getGlobalMutex());
98cdf0e10cSrcweir               if (!pInstance)
99cdf0e10cSrcweir                   pInstance = new T;
100cdf0e10cSrcweir           }
101cdf0e10cSrcweir           return pInstance;
102cdf0e10cSrcweir       }
103cdf0e10cSrcweir 
104cdf0e10cSrcweir     Code:
105cdf0e10cSrcweir 
106cdf0e10cSrcweir       #include "rtl/instance.hxx"
107cdf0e10cSrcweir       #include "osl/getglobalmutex.hxx"
108cdf0e10cSrcweir 
109cdf0e10cSrcweir       namespace {
110cdf0e10cSrcweir           struct Init
111cdf0e10cSrcweir           {
112cdf0e10cSrcweir               T * operator()()
113cdf0e10cSrcweir               {
114cdf0e10cSrcweir                   return new T;
115cdf0e10cSrcweir               }
116cdf0e10cSrcweir           };
117cdf0e10cSrcweir       }
118cdf0e10cSrcweir 
119cdf0e10cSrcweir       T * getInstance()
120cdf0e10cSrcweir       {
121cdf0e10cSrcweir           return rtl_Instance< T, Init, ::osl::MutexGuard,
122cdf0e10cSrcweir                                ::osl::GetGlobalMutex >::create(
123cdf0e10cSrcweir               Init(), ::osl::GetGlobalMutex());
124cdf0e10cSrcweir       }
125cdf0e10cSrcweir 
126cdf0e10cSrcweir     3  Other guard/mutex
127cdf0e10cSrcweir 
128cdf0e10cSrcweir     Pattern:
129cdf0e10cSrcweir 
130cdf0e10cSrcweir       T * getInstance()
131cdf0e10cSrcweir       {
132cdf0e10cSrcweir           static T * pInstance = 0;
133cdf0e10cSrcweir           if (!pInstance)
134cdf0e10cSrcweir           {
135cdf0e10cSrcweir               SomeGuard aGuard(pSomeMutex);
136cdf0e10cSrcweir               if (!pInstance)
137cdf0e10cSrcweir               {
138cdf0e10cSrcweir                   static T aInstance;
139cdf0e10cSrcweir                   pInstance = &aInstance;
140cdf0e10cSrcweir               }
141cdf0e10cSrcweir           }
142cdf0e10cSrcweir           return pInstance;
143cdf0e10cSrcweir       }
144cdf0e10cSrcweir 
145cdf0e10cSrcweir     Code:
146cdf0e10cSrcweir 
147cdf0e10cSrcweir       #include "rtl/instance.hxx"
148cdf0e10cSrcweir 
149cdf0e10cSrcweir       namespace {
150cdf0e10cSrcweir           struct InitInstance
151cdf0e10cSrcweir           {
152cdf0e10cSrcweir               T * operator()()
153cdf0e10cSrcweir               {
154cdf0e10cSrcweir                   static T aInstance;
155cdf0e10cSrcweir                   return &aInstance;
156cdf0e10cSrcweir               }
157cdf0e10cSrcweir           };
158cdf0e10cSrcweir 
159cdf0e10cSrcweir           struct InitGuard
160cdf0e10cSrcweir           {
161cdf0e10cSrcweir               SomeMutex * operator()()
162cdf0e10cSrcweir               {
163cdf0e10cSrcweir                   return pSomeMutex;
164cdf0e10cSrcweir               }
165cdf0e10cSrcweir           };
166cdf0e10cSrcweir       }
167cdf0e10cSrcweir 
168cdf0e10cSrcweir       T * getInstance()
169cdf0e10cSrcweir       {
170cdf0e10cSrcweir           return rtl_Instance< T, InitInstance,
171cdf0e10cSrcweir                                SomeGuard, InitGuard >::create(
172cdf0e10cSrcweir               InitInstance(), InitMutex());
173cdf0e10cSrcweir       }
174cdf0e10cSrcweir 
175cdf0e10cSrcweir     4  Calculate extra data
176cdf0e10cSrcweir 
177cdf0e10cSrcweir     Pattern:
178cdf0e10cSrcweir 
179cdf0e10cSrcweir       T * getInstance()
180cdf0e10cSrcweir       {
181cdf0e10cSrcweir           static T * pInstance = 0;
182cdf0e10cSrcweir           if (!pInstance)
183cdf0e10cSrcweir           {
184cdf0e10cSrcweir               Data aData(...);
185cdf0e10cSrcweir               ::osl::MutexGuard aGuard(::osl::Mutex::getGlobalMutex());
186cdf0e10cSrcweir               if (!pInstance)
187cdf0e10cSrcweir               {
188cdf0e10cSrcweir                   static T aInstance(aData);
189cdf0e10cSrcweir                   pInstance = &aInstance;
190cdf0e10cSrcweir               }
191cdf0e10cSrcweir           }
192cdf0e10cSrcweir           return pInstance;
193cdf0e10cSrcweir       }
194cdf0e10cSrcweir 
195cdf0e10cSrcweir     Code:
196cdf0e10cSrcweir 
197cdf0e10cSrcweir       #include "rtl/instance.hxx"
198cdf0e10cSrcweir       #include "osl/getglobalmutex.hxx"
199cdf0e10cSrcweir 
200cdf0e10cSrcweir       namespace {
201cdf0e10cSrcweir           struct InitInstance
202cdf0e10cSrcweir           {
203cdf0e10cSrcweir               T * operator()()
204cdf0e10cSrcweir               {
205cdf0e10cSrcweir                   static T aInstance;
206cdf0e10cSrcweir                   return &aInstance;
207cdf0e10cSrcweir               }
208cdf0e10cSrcweir           }
209cdf0e10cSrcweir 
210cdf0e10cSrcweir           struct InitData
211cdf0e10cSrcweir           {
212cdf0e10cSrcweir               Data const & operator()()
213cdf0e10cSrcweir               {
214cdf0e10cSrcweir                   return ...;
215cdf0e10cSrcweir               }
216cdf0e10cSrcweir           }
217cdf0e10cSrcweir       }
218cdf0e10cSrcweir 
219cdf0e10cSrcweir       T * getInstance()
220cdf0e10cSrcweir       {
221cdf0e10cSrcweir           return rtl_Instance< T, InitInstance,
222cdf0e10cSrcweir                                ::osl::Mutex, ::osl::GetGlobalMutex,
223cdf0e10cSrcweir                                Data, InitData >::create(
224cdf0e10cSrcweir               InitInstance(), ::osl::GetGlobalMutex(), InitData());
225cdf0e10cSrcweir       }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir     Some comments:
228cdf0e10cSrcweir 
229cdf0e10cSrcweir     For any instantiation of rtl_Instance, at most one call to a create method
230*86e1cf34SPedro Giffuni     may occur in the program code:  Each occurrence of a create method within
231cdf0e10cSrcweir     the program code is supposed to return a fresh object instance on the
232cdf0e10cSrcweir     first call, and that same object instance on subsequent calls; but
233*86e1cf34SPedro Giffuni     independent occurrences of create methods are supposed to return
234cdf0e10cSrcweir     independent object instances.  Since there is a one-to-one correspondence
235cdf0e10cSrcweir     between object instances and instantiations of rtl_Instance, the
236cdf0e10cSrcweir     requirement should be clear.  One measure to enforce the requirement is
237cdf0e10cSrcweir     that rtl_Instance lives in an unnamed namespace, so that instantiations of
238cdf0e10cSrcweir     rtl_Instance in different translation units will definitely be different
239cdf0e10cSrcweir     instantiations.  A drawback of that measure is that the name of the class
240cdf0e10cSrcweir     needs a funny "hand coded" prefix "rtl_" instead of a proper namespace
241cdf0e10cSrcweir     prefix like "::rtl::".
242cdf0e10cSrcweir 
243*86e1cf34SPedro Giffuni     A known problem with this template is when two occurrences of calls to
244cdf0e10cSrcweir     create methods with identical template arguments appear in one translation
245cdf0e10cSrcweir     unit.  Those two places will share a single object instance.  This can be
246cdf0e10cSrcweir     avoided by using different Init structs (see the above code samples) in
247cdf0e10cSrcweir     the two places.
248cdf0e10cSrcweir 
249cdf0e10cSrcweir     There is no need to make m_pInstance volatile, in order to avoid usage of
250cdf0e10cSrcweir     stale copies of m_pInstance:  At the first check, a thread will see that
251cdf0e10cSrcweir     m_pInstance contains either 0 or a valid pointer.  If it contains a valid
252cdf0e10cSrcweir     pointer, it cannot be stale, and that pointer is used.  If it contains 0,
253cdf0e10cSrcweir     acquiring the mutex will ensure that the second check sees a non-stale
254cdf0e10cSrcweir     value in all cases.
255cdf0e10cSrcweir 
256cdf0e10cSrcweir     On some compilers, the create methods would not be inlined if they
257cdf0e10cSrcweir     contained any static variables, so m_pInstance is made a class member
258cdf0e10cSrcweir     instead (and the create methods are inlined).  But on MSC, the definition
259cdf0e10cSrcweir     of the class member m_pInstance would cause compilation to fail with an
260cdf0e10cSrcweir     internal compiler error.  Since MSC is able to inline methods containing
261cdf0e10cSrcweir     static variables, m_pInstance is moved into the methods there.  Note that
262cdf0e10cSrcweir     this only works well because for any instantiation of rtl_Instance at most
263cdf0e10cSrcweir     one call to a create method should be present, anyway.
264cdf0e10cSrcweir  */
265cdf0e10cSrcweir template< typename Inst, typename InstCtor,
266cdf0e10cSrcweir           typename Guard, typename GuardCtor,
267cdf0e10cSrcweir           typename Data = int, typename DataCtor = int >
268cdf0e10cSrcweir class rtl_Instance
269cdf0e10cSrcweir {
270cdf0e10cSrcweir public:
create(InstCtor aInstCtor,GuardCtor aGuardCtor)271cdf0e10cSrcweir     static inline Inst * create(InstCtor aInstCtor, GuardCtor aGuardCtor)
272cdf0e10cSrcweir     {
273cdf0e10cSrcweir #if defined _MSC_VER
274cdf0e10cSrcweir         static Inst * m_pInstance = 0;
275cdf0e10cSrcweir #endif // _MSC_VER
276cdf0e10cSrcweir         Inst * p = m_pInstance;
277cdf0e10cSrcweir         if (!p)
278cdf0e10cSrcweir         {
279cdf0e10cSrcweir             Guard aGuard(aGuardCtor());
280cdf0e10cSrcweir             p = m_pInstance;
281cdf0e10cSrcweir             if (!p)
282cdf0e10cSrcweir             {
283cdf0e10cSrcweir                 p = aInstCtor();
284cdf0e10cSrcweir                 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
285cdf0e10cSrcweir                 m_pInstance = p;
286cdf0e10cSrcweir             }
287cdf0e10cSrcweir         }
288cdf0e10cSrcweir         else
289cdf0e10cSrcweir         {
290cdf0e10cSrcweir             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
291cdf0e10cSrcweir         }
292cdf0e10cSrcweir         return p;
293cdf0e10cSrcweir     }
294cdf0e10cSrcweir 
create(InstCtor aInstCtor,GuardCtor aGuardCtor,DataCtor aDataCtor)295cdf0e10cSrcweir     static inline Inst * create(InstCtor aInstCtor, GuardCtor aGuardCtor,
296cdf0e10cSrcweir                                 DataCtor aDataCtor)
297cdf0e10cSrcweir     {
298cdf0e10cSrcweir #if defined _MSC_VER
299cdf0e10cSrcweir         static Inst * m_pInstance = 0;
300cdf0e10cSrcweir #endif // _MSC_VER
301cdf0e10cSrcweir         Inst * p = m_pInstance;
302cdf0e10cSrcweir         if (!p)
303cdf0e10cSrcweir         {
304cdf0e10cSrcweir             Data aData(aDataCtor());
305cdf0e10cSrcweir             Guard aGuard(aGuardCtor());
306cdf0e10cSrcweir             p = m_pInstance;
307cdf0e10cSrcweir             if (!p)
308cdf0e10cSrcweir             {
309cdf0e10cSrcweir                 p = aInstCtor(aData);
310cdf0e10cSrcweir                 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
311cdf0e10cSrcweir                 m_pInstance = p;
312cdf0e10cSrcweir             }
313cdf0e10cSrcweir         }
314cdf0e10cSrcweir         else
315cdf0e10cSrcweir         {
316cdf0e10cSrcweir             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
317cdf0e10cSrcweir         }
318cdf0e10cSrcweir         return p;
319cdf0e10cSrcweir     }
320cdf0e10cSrcweir 
321cdf0e10cSrcweir private:
322cdf0e10cSrcweir #if !defined _MSC_VER
323cdf0e10cSrcweir     static Inst * m_pInstance;
324cdf0e10cSrcweir #endif // _MSC_VER
325cdf0e10cSrcweir };
326cdf0e10cSrcweir 
327cdf0e10cSrcweir #if !defined _MSC_VER
328cdf0e10cSrcweir template< typename Inst, typename InstCtor,
329cdf0e10cSrcweir           typename Guard, typename GuardCtor,
330cdf0e10cSrcweir           typename Data, typename DataCtor >
331cdf0e10cSrcweir Inst *
332cdf0e10cSrcweir rtl_Instance< Inst, InstCtor, Guard, GuardCtor, Data, DataCtor >::m_pInstance
333cdf0e10cSrcweir = 0;
334cdf0e10cSrcweir #endif // _MSC_VER
335cdf0e10cSrcweir 
336cdf0e10cSrcweir }
337cdf0e10cSrcweir 
338cdf0e10cSrcweir namespace rtl {
339cdf0e10cSrcweir 
340cdf0e10cSrcweir /** Helper base class for a late-initialized (default-constructed)
341cdf0e10cSrcweir     static variable, implementing the double-checked locking pattern correctly.
342cdf0e10cSrcweir 
343cdf0e10cSrcweir     @derive
344cdf0e10cSrcweir     Derive from this class (common practice), e.g.
345cdf0e10cSrcweir     <pre>
346cdf0e10cSrcweir     struct MyStatic : public rtl::Static<MyType, MyStatic> {};
347cdf0e10cSrcweir     ...
348cdf0e10cSrcweir     MyType & rStatic = MyStatic::get();
349cdf0e10cSrcweir     ...
350cdf0e10cSrcweir     </pre>
351cdf0e10cSrcweir 
352cdf0e10cSrcweir     @tplparam T
353cdf0e10cSrcweir               variable's type
354cdf0e10cSrcweir     @tplparam Unique
355cdf0e10cSrcweir               Implementation trick to make the inner static holder unique,
356cdf0e10cSrcweir               using the outer class
357cdf0e10cSrcweir               (the one that derives from this base class)
358cdf0e10cSrcweir */
359cdf0e10cSrcweir template<typename T, typename Unique>
360cdf0e10cSrcweir class Static {
361cdf0e10cSrcweir public:
362cdf0e10cSrcweir     /** Gets the static.  Mutual exclusion is performed using the
363cdf0e10cSrcweir         osl global mutex.
364cdf0e10cSrcweir 
365cdf0e10cSrcweir         @return
366cdf0e10cSrcweir                 static variable
367cdf0e10cSrcweir     */
get()368cdf0e10cSrcweir     static T & get() {
369cdf0e10cSrcweir         return *rtl_Instance<
370cdf0e10cSrcweir             T, StaticInstance,
371cdf0e10cSrcweir             ::osl::MutexGuard, ::osl::GetGlobalMutex >::create(
372cdf0e10cSrcweir                 StaticInstance(), ::osl::GetGlobalMutex() );
373cdf0e10cSrcweir     }
374cdf0e10cSrcweir private:
375cdf0e10cSrcweir     struct StaticInstance {
operator ()rtl::Static::StaticInstance376cdf0e10cSrcweir         T * operator () () {
377cdf0e10cSrcweir             static T instance;
378cdf0e10cSrcweir             return &instance;
379cdf0e10cSrcweir         }
380cdf0e10cSrcweir     };
381cdf0e10cSrcweir };
382cdf0e10cSrcweir 
383cdf0e10cSrcweir /** Helper class for a late-initialized static aggregate, e.g. an array,
384cdf0e10cSrcweir     implementing the double-checked locking pattern correctly.
385cdf0e10cSrcweir 
386cdf0e10cSrcweir     @tplparam T
387cdf0e10cSrcweir               aggregate's element type
388cdf0e10cSrcweir     @tplparam InitAggregate
389cdf0e10cSrcweir               initializer functor class
390cdf0e10cSrcweir */
391cdf0e10cSrcweir template<typename T, typename InitAggregate>
392cdf0e10cSrcweir class StaticAggregate {
393cdf0e10cSrcweir public:
394cdf0e10cSrcweir     /** Gets the static aggregate, late-initializing.
395cdf0e10cSrcweir         Mutual exclusion is performed using the osl global mutex.
396cdf0e10cSrcweir 
397cdf0e10cSrcweir         @return
398cdf0e10cSrcweir                 aggregate
399cdf0e10cSrcweir     */
get()400cdf0e10cSrcweir     static T * get() {
401cdf0e10cSrcweir         return rtl_Instance<
402cdf0e10cSrcweir             T, InitAggregate,
403cdf0e10cSrcweir             ::osl::MutexGuard, ::osl::GetGlobalMutex >::create(
404cdf0e10cSrcweir                 InitAggregate(), ::osl::GetGlobalMutex() );
405cdf0e10cSrcweir     }
406cdf0e10cSrcweir };
407cdf0e10cSrcweir 
408cdf0e10cSrcweir /** Helper base class for a late-initialized static variable,
409cdf0e10cSrcweir     implementing the double-checked locking pattern correctly.
410cdf0e10cSrcweir 
411cdf0e10cSrcweir     @derive
412cdf0e10cSrcweir     Derive from this class (common practice),
413cdf0e10cSrcweir     providing an initializer functor class, e.g.
414cdf0e10cSrcweir     <pre>
415cdf0e10cSrcweir     struct MyStatic : public rtl::StaticWithInit<MyType, MyStatic> {
416cdf0e10cSrcweir         MyType operator () () {
417cdf0e10cSrcweir             ...
418cdf0e10cSrcweir             return MyType( ... );
419cdf0e10cSrcweir         }
420cdf0e10cSrcweir     };
421cdf0e10cSrcweir     ...
422cdf0e10cSrcweir     MyType & rStatic = MyStatic::get();
423cdf0e10cSrcweir     ...
424cdf0e10cSrcweir     </pre>
425cdf0e10cSrcweir 
426cdf0e10cSrcweir     @tplparam T
427cdf0e10cSrcweir               variable's type
428cdf0e10cSrcweir     @tplparam InitData
429cdf0e10cSrcweir               initializer functor class
430cdf0e10cSrcweir     @tplparam Unique
431cdf0e10cSrcweir               Implementation trick to make the inner static holder unique,
432cdf0e10cSrcweir               using the outer class
433cdf0e10cSrcweir               (the one that derives from this base class).
434cdf0e10cSrcweir               Default is InitData (common practice).
435cdf0e10cSrcweir     @tplparam Data
436cdf0e10cSrcweir               Initializer functor's return type.
437cdf0e10cSrcweir               Default is T (common practice).
438cdf0e10cSrcweir */
439cdf0e10cSrcweir template<typename T, typename InitData,
440cdf0e10cSrcweir          typename Unique = InitData, typename Data = T>
441cdf0e10cSrcweir class StaticWithInit {
442cdf0e10cSrcweir public:
443cdf0e10cSrcweir     /** Gets the static.  Mutual exclusion is performed using the
444cdf0e10cSrcweir         osl global mutex.
445cdf0e10cSrcweir 
446cdf0e10cSrcweir         @return
447cdf0e10cSrcweir                 static variable
448cdf0e10cSrcweir     */
get()449cdf0e10cSrcweir     static T & get() {
450cdf0e10cSrcweir         return *rtl_Instance<
451cdf0e10cSrcweir             T, StaticInstanceWithInit,
452cdf0e10cSrcweir             ::osl::MutexGuard, ::osl::GetGlobalMutex,
453cdf0e10cSrcweir             Data, InitData >::create( StaticInstanceWithInit(),
454cdf0e10cSrcweir                                       ::osl::GetGlobalMutex(),
455cdf0e10cSrcweir                                       InitData() );
456cdf0e10cSrcweir     }
457cdf0e10cSrcweir private:
458cdf0e10cSrcweir     struct StaticInstanceWithInit {
operator ()rtl::StaticWithInit::StaticInstanceWithInit459cdf0e10cSrcweir         T * operator () ( Data d ) {
460cdf0e10cSrcweir             static T instance(d);
461cdf0e10cSrcweir             return &instance;
462cdf0e10cSrcweir         }
463cdf0e10cSrcweir     };
464cdf0e10cSrcweir };
465cdf0e10cSrcweir 
466cdf0e10cSrcweir } // namespace rtl
467cdf0e10cSrcweir 
468cdf0e10cSrcweir #endif // INCLUDED_RTL_INSTANCE_HXX
469