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