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