Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

714 lines
20 KiB

  1. /*
  2. * S I N G L T O N . H
  3. *
  4. * Singleton (per-process global) classes
  5. *
  6. * Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
  7. */
  8. #ifndef _SINGLTON_H_
  9. #define _SINGLTON_H_
  10. #include <caldbg.h>
  11. // ========================================================================
  12. //
  13. // TEMPLATE CLASS Singleton
  14. //
  15. // Use this template to implement classes that can only have one instance.
  16. // NOTE: For ref-counted or on-demand global objects, see below
  17. // (RefCountedGlobal and OnDemandGlobal).
  18. //
  19. // The Singleton template provides the following:
  20. //
  21. // o a common memory layout for singleton classes which
  22. // allows template folding to reduce overall code size.
  23. //
  24. // o an instantiation mechanism that verifies (asserts)
  25. // that only instance of your class ever exists.
  26. //
  27. // o asserts to catch any code which attempts to use
  28. // your class when it's not initialized.
  29. //
  30. // To use this template, declare your class like this:
  31. //
  32. // class YourClass : private Singleton<YourClass>
  33. // {
  34. // //
  35. // // Declare Singleton as a friend of YourClass
  36. // // if YourClass's constructor is private (which it
  37. // // should be since YourClass is a singleton and
  38. // // should not be allowed to arbitrarily create
  39. // // instances of it).
  40. // //
  41. // friend class Singleton<YourClass>;
  42. //
  43. // //
  44. // // YourClass private members. Since the 'staticness'
  45. // // of YourClass is provided entirely by this template,
  46. // // you do not need to declare your members as 'static'
  47. // // and you should use standard Hungarian class member
  48. // // naming conventions (e.g. m_dwShoeSize).
  49. // //
  50. // [...]
  51. //
  52. // public:
  53. // //
  54. // // Public declarations for YourClass. Among these should
  55. // // be static functions to init and deinit YourClass which
  56. // // would call CreateInstance() and DestroyInstance()
  57. // // respectively. Or, you could just expose these functions
  58. // // directly to clients of YourClass with using declarations:
  59. // //
  60. // // using Singleton<YourClass>::CreateInstance;
  61. // // using Singleton<YourClass>::DestroyInstance;
  62. // //
  63. // // Similarly, YourClass will probably have additional
  64. // // static methods which access or operate on the
  65. // // singleton instance. These will call Instance()
  66. // // to get at the global instance. Or, though it's
  67. // // not recommended from an encapsulation standpoint,
  68. // // you could expose the global instance directly to
  69. // // clients with:
  70. // //
  71. // // using Singleton<YourClass>::Instance;
  72. // //
  73. // [...]
  74. // };
  75. //
  76. template<class _X>
  77. class Singleton
  78. {
  79. //
  80. // Space for the sole instance
  81. //
  82. static BYTE sm_rgbInstance[];
  83. //
  84. // Pointer to the instance
  85. //
  86. static _X * sm_pInstance;
  87. public:
  88. // STATICS
  89. //
  90. //
  91. // Create the single, global instance of class _X.
  92. //
  93. static _X& CreateInstance()
  94. {
  95. //
  96. // This actually calls Singleton::new()
  97. // (defined below), but calls to new()
  98. // must always be unqualified.
  99. //
  100. return *(new _X());
  101. }
  102. //
  103. // Destroy the single, global instance of class _X.
  104. //
  105. static VOID DestroyInstance()
  106. {
  107. //
  108. // This actually calls Singleton::delete()
  109. // (defined below), but calls to delete()
  110. // must always be unqualified.
  111. //
  112. if (sm_pInstance)
  113. delete sm_pInstance;
  114. }
  115. //
  116. // Provide access to the single, global instance of class _X.
  117. //
  118. static BOOL FIsInstantiated()
  119. {
  120. return !!sm_pInstance;
  121. }
  122. static _X& Instance()
  123. {
  124. Assert( sm_pInstance );
  125. return *sm_pInstance;
  126. }
  127. //
  128. // Singleton operator new and operator delete "allocate"
  129. // space for the object in static memory. These must be
  130. // defined public for syntactic reasons. Do NOT call them
  131. // directly!! Use CreateInstance()/DestroyInstance().
  132. //
  133. static void * operator new(size_t)
  134. {
  135. Assert( !sm_pInstance );
  136. //
  137. // Just return a pointer to the space
  138. // in which to instantiate the object.
  139. //
  140. sm_pInstance = reinterpret_cast<_X *>(sm_rgbInstance);
  141. return sm_pInstance;
  142. }
  143. static void operator delete(void *, size_t)
  144. {
  145. Assert( sm_pInstance );
  146. //
  147. // Since nothing was done to allocate space
  148. // for the instance, we don't do anything
  149. // here to free it.
  150. //
  151. sm_pInstance = NULL;
  152. }
  153. };
  154. //
  155. // Space for the sole instance of class _X
  156. //
  157. template<class _X>
  158. BYTE Singleton<_X>::sm_rgbInstance[sizeof(_X)] = {0};
  159. //
  160. // Pointer to the instance
  161. //
  162. template<class _X>
  163. _X * Singleton<_X>::sm_pInstance = NULL;
  164. // ========================================================================
  165. //
  166. // CLASS _Empty
  167. //
  168. // A completely empty, but instantiatable class. Use the _Empty class
  169. // to get around the syntactic inability to instantiate anything of
  170. // type void (or VOID).
  171. //
  172. // In retail builds, _Empty has the same memory footprint and code
  173. // impact as void -- none.
  174. //
  175. // See the RefCountedGlobal template below for a usage example.
  176. //
  177. class _Empty
  178. {
  179. // NOT IMPLEMENTED
  180. //
  181. _Empty( const _Empty& );
  182. _Empty& operator=( const _Empty& );
  183. public:
  184. _Empty() {}
  185. ~_Empty() {}
  186. };
  187. // ========================================================================
  188. //
  189. // TEMPLATE CLASS RefCountedGlobal
  190. //
  191. // Use this template as boilerplate for any class that encapsulates
  192. // a global, refcounted initialization/deinitialization process.
  193. //
  194. // This template maintains proper refcounting and synchronization when
  195. // there are multiple threads trying to initialize and deinitialize
  196. // references at the same time. And it does so without a critical
  197. // section.
  198. //
  199. // To use this template, declare your class like this:
  200. //
  201. // class YourClass : private RefCountedGlobal<YourClass>
  202. // {
  203. // //
  204. // // Declare Singleton and RefCountedGlobal as friends
  205. // // of YourClass so that they can call your private
  206. // // initialization functions.
  207. // //
  208. // friend class Singleton<YourClass>;
  209. // friend class RefCountedGlobal<YourClass>;
  210. //
  211. // //
  212. // // Private declarations for YourClass
  213. // //
  214. // [...]
  215. //
  216. // //
  217. // // Failable initialization function. This function
  218. // // should perform any failable initialization of the
  219. // // instance of YourClass. It should return TRUE
  220. // // if initialization succeeds, and FALSE otherwise.
  221. // // If YourClass does not have any initialization that
  222. // // can fail then you should implement this function inline
  223. // // to just return TRUE.
  224. // //
  225. // BOOL FInit();
  226. //
  227. // public:
  228. // //
  229. // // Public declarations for YourClass. Among these should
  230. // // be static functions to init and deinit YourClass. These
  231. // // functions would call DwInitRef() and DeinitRef() respectively.
  232. // // Or, you could just expose DwInitRef() and DeinitRef()
  233. // // directly to clients of YourClass with using declarations:
  234. // //
  235. // // using RefCountedGlobal<YourClass>::DwInitRef;
  236. // // using RefCountedGlobal<YourClass>::DeinitRef;
  237. // //
  238. // [...]
  239. // };
  240. //
  241. // If YourClass::FInit() succeeds (returns TRUE), then DwInitRef()
  242. // returns the new refcount. If YourClass::FInit() fails (returns
  243. // FALSE), then DwInitRef() returns 0.
  244. //
  245. // See \cal\src\inc\memx.h for sample usage.
  246. //
  247. // If YourClass::FInit() requires initialization parameters, you can
  248. // still use the RefCountedGlobal template. You just need to provide
  249. // your parameter type in the template instantiation and declare your
  250. // FInit() to take a const reference to a parameter of that type:
  251. //
  252. // class YourClass : private RefCountedGlobal<YourClass, YourParameterType>
  253. // {
  254. // //
  255. // // Declare Singleton and RefCountedGlobal as friends
  256. // // of YourClass so that htey can call your private
  257. // // initialization functions.
  258. // //
  259. // // Note the added parameter type to the RefCountedGlobal
  260. // // declaration.
  261. // //
  262. // friend class Singleton<YourClass>;
  263. // friend class RefCountedGlobal<YourClass, YourParameterType>;
  264. //
  265. // //
  266. // // Private declarations for YourClass
  267. // //
  268. // [...]
  269. //
  270. // //
  271. // // Failable initialization function. This function
  272. // // now takes a const ref to the initialization parameters.
  273. // //
  274. // BOOL FInit( const YourParameterType& initParam );
  275. //
  276. // public:
  277. // //
  278. // // Public declarations for YourClass
  279. // //
  280. // [...]
  281. // };
  282. //
  283. // See \cal\src\httpext\entry.cpp for an example of this usage.
  284. //
  285. template<class _X, class _ParmType = _Empty>
  286. class RefCountedGlobal : private Singleton<_X>
  287. {
  288. //
  289. // The object's reference count.
  290. //
  291. static LONG sm_lcRef;
  292. //
  293. // Member template that generates an appropriately-typed,
  294. // (inline) function that calls _X::FInit with initialization
  295. // parameters.
  296. //
  297. template<class _P> static BOOL
  298. FInit( const _P& parms ) { return Instance().FInit( parms ); }
  299. //
  300. // Specialization of the above member template for
  301. // the _Empty parameter type, which calls _X::FInit
  302. // without initialization parameters.
  303. //
  304. static BOOL FInit( const _Empty& ) { return Instance().FInit(); }
  305. protected:
  306. //
  307. // Set of states which describe the object's state
  308. // of initialization. The object's state is
  309. // STATE_UNKNOWN while it is being initialized or
  310. // deinitialized.
  311. //
  312. enum
  313. {
  314. STATE_UNINITIALIZED,
  315. STATE_INITIALIZED,
  316. STATE_UNKNOWN
  317. };
  318. static LONG sm_lState;
  319. //
  320. // Expose access to the single instance of class _X
  321. //
  322. using Singleton<_X>::Instance;
  323. //
  324. // Expose operator new and operator delete from
  325. // the Singleton template so that they will be
  326. // used rather than the default new and delete
  327. // to "allocate" space for the instance of class _X.
  328. //
  329. using Singleton<_X>::operator new;
  330. using Singleton<_X>::operator delete;
  331. static BOOL FInitialized()
  332. {
  333. return sm_lState == STATE_INITIALIZED;
  334. }
  335. static LONG CRef()
  336. {
  337. return sm_lcRef;
  338. }
  339. public:
  340. static DWORD DwInitRef( const _ParmType& parms )
  341. {
  342. LONG lcRef;
  343. //
  344. // Assert the invariant condition that we never have a
  345. // reference without the state being initialized.
  346. //
  347. Assert( sm_lState != STATE_INITIALIZED || sm_lcRef >= 1 );
  348. //
  349. // Add the reference for the instance we're about
  350. // to initialize. Doing this now simplifies the
  351. // code below at the expense of having to decrement
  352. // if first time initialization (FInit()) fails.
  353. // The only thing critical to the design is that
  354. // at any point, when sm_lState is STATE_INITIALIZED,
  355. // sm_lcRef is at least 1.
  356. //
  357. lcRef = InterlockedIncrement( &sm_lcRef );
  358. Assert( lcRef > 0 );
  359. //
  360. // Don't proceed until the object is initialized.
  361. //
  362. while ( sm_lState != STATE_INITIALIZED )
  363. {
  364. //
  365. // Simultaneously check whether initialization has
  366. // started and, if it has not, start it.
  367. //
  368. LONG lStatePrev = InterlockedCompareExchange(
  369. &sm_lState,
  370. STATE_UNKNOWN,
  371. STATE_UNINITIALIZED );
  372. //
  373. // If we're starting first time initialization,
  374. // then create and initialize the sole instance.
  375. //
  376. if ( lStatePrev == STATE_UNINITIALIZED )
  377. {
  378. CreateInstance();
  379. // This calls our private member template FInit()
  380. // (declared above), which in turn calls _X::Finit()
  381. // with the appropriate parameters.
  382. //
  383. if ( FInit( parms ) )
  384. {
  385. sm_lState = STATE_INITIALIZED;
  386. break;
  387. }
  388. // We failed to init.
  389. // Tear down now.
  390. //
  391. Assert( lcRef == 1 );
  392. Assert( sm_lState == STATE_UNKNOWN );
  393. // Let go of our ref on the object.
  394. // Destroy the object.
  395. // And LAST, set the state to UNINITIALIZED.
  396. // NOTE: This will let the next caller through the
  397. // InterlockedCompare above.
  398. //
  399. InterlockedDecrement( &sm_lcRef );
  400. DestroyInstance();
  401. sm_lState = STATE_UNINITIALIZED;
  402. return 0;
  403. }
  404. //
  405. // If first time initialization is in progress on
  406. // another thread, then get out of the way so
  407. // it can finish.
  408. //
  409. //$OPT We should probably spin rather than Sleep()
  410. //$OPT on multi-proc machines on the assumption that
  411. //$OPT we only get here on a processor other than
  412. //$OPT the one which is doing the initialization
  413. //$OPT and we don't want to invite a task switch
  414. //$OPT by calling Sleep() while we are waiting
  415. //$OPT for initialization to complete.
  416. //
  417. if ( lStatePrev == STATE_UNKNOWN )
  418. Sleep(0);
  419. }
  420. //
  421. // At this point, there must be at least
  422. // one initialized reference.
  423. //
  424. Assert( sm_lState == STATE_INITIALIZED );
  425. Assert( sm_lcRef > 0 );
  426. return static_cast<DWORD>(lcRef);
  427. }
  428. static VOID DeinitRef()
  429. {
  430. //
  431. // At this point, there must be at least
  432. // one initialized reference.
  433. //
  434. Assert( sm_lState == STATE_INITIALIZED );
  435. Assert( sm_lcRef > 0 );
  436. //
  437. // Remove that reference. If it is the last
  438. // then deinit the object.
  439. //
  440. if ( 0 == InterlockedDecrement( &sm_lcRef ) )
  441. {
  442. //
  443. // After releasing the last reference, declare that
  444. // the object is in an unknown state. This prevents
  445. // other threads trying to re-initialize the object
  446. // from proceeding until we're done.
  447. //
  448. sm_lState = STATE_UNKNOWN;
  449. //
  450. // There is a tiny window between decrementing the
  451. // refcount and changing the state where another
  452. // initialization could have come through. Test this
  453. // by rechecking the refcount.
  454. //
  455. if ( 0 == sm_lcRef )
  456. {
  457. //
  458. // If the refcount is still zero, then no
  459. // initializations happened before we changed
  460. // states. At this point, if an initialization
  461. // starts, it will block until we change state,
  462. // so it is safe to actually destroy the instance.
  463. //
  464. DestroyInstance();
  465. //
  466. // Once the object has been deinitialized, update
  467. // the state information. This unblocks any
  468. // initializations waiting to happen.
  469. //
  470. sm_lState = STATE_UNINITIALIZED;
  471. }
  472. else // refcount is now non-zero
  473. {
  474. //
  475. // If the refcount is no longer zero, then an
  476. // initialization happened between decrementing
  477. // the refcount above and entering the unknown
  478. // state. When that happens, DO NOT deinit --
  479. // there is now another valid reference somewhere.
  480. // Instead, just restore the object's state to let
  481. // other references proceed.
  482. //
  483. sm_lState = STATE_INITIALIZED;
  484. }
  485. }
  486. //
  487. // Assert the invariant condition that we never have a
  488. // reference without the state being initialized.
  489. //
  490. Assert( sm_lState != STATE_INITIALIZED || sm_lcRef >= 1 );
  491. }
  492. // This provides a no-parameter version of DwInitRef
  493. // for clients that do not need any parameters in FInit().
  494. //
  495. static DWORD DwInitRef()
  496. {
  497. _Empty e;
  498. return DwInitRef( e );
  499. }
  500. };
  501. template<class _X, class _ParmType>
  502. LONG RefCountedGlobal<_X, _ParmType>::sm_lcRef = 0;
  503. template<class _X, class _ParmType>
  504. LONG RefCountedGlobal<_X, _ParmType>::sm_lState = STATE_UNINITIALIZED;
  505. // ========================================================================
  506. //
  507. // TEMPLATE CLASS OnDemandGlobal
  508. //
  509. // Use this template to implement a global object which should be
  510. // initialized on its first use ("on demand") and then explicitly
  511. // deinitialized once if it was ever used.
  512. //
  513. // The most common usage is with global objects that ideally are never
  514. // used or for which up-front initialization is prohibitively
  515. // expensive. However, once the object has been initialied, it should
  516. // remain initialized (to avoid having to initialize it again) until
  517. // it is explicitly deinitialized.
  518. //
  519. // !!! OnDemandGlobal DOES NOT provide refcounting functionality to
  520. // consumers -- It uses refcounting internally, but is not intended
  521. // to expose it to callers. If you want refcounting, use RefCountedGlobal.
  522. // If you call DeinitIfUsed(), the instance WILL be destroyed if it
  523. // exists. In particular, calling code MUST ensure that DeinitIfUsed()
  524. // is not called while any other thread is inside FInitOnFirstUse().
  525. // Failure to do so can cause FInitOnFirstUse() to return with the
  526. // object uninitialized.
  527. //
  528. // Usage:
  529. //
  530. // class YourClass : private OnDemandGlobal<YourClass>
  531. // {
  532. // //
  533. // // Declare Singleton and RefCountedGlobal as friends
  534. // // of YourClass so that they can call your private
  535. // // creation/initialization functions.
  536. // //
  537. // friend class Singleton<YourClass>;
  538. // friend class RefCountedGlobal<YourClass>;
  539. //
  540. // //
  541. // // Private declarations for YourClass
  542. // //
  543. // [...]
  544. //
  545. // //
  546. // // Failable initialization function. This function
  547. // // should perform any failable initialization of the
  548. // // instance of YourClass. It should return TRUE
  549. // // if initialization succeeds, and FALSE otherwise.
  550. // // If YourClass does not have any initialization that
  551. // // can fail then you should implement this function inline
  552. // // to just return TRUE.
  553. // //
  554. // BOOL FInit();
  555. //
  556. // public:
  557. // //
  558. // // Public declarations for YourClass. Among these should
  559. // // be static functions to init and deinit YourClass. These
  560. // // functions would call FInitOnFirstUse() and DeinitIfUsed()
  561. // // respectively. Or, you could just expose FInitOnFirstUse()
  562. // // and DeinitIfUsed() directly to clients of YourClass with
  563. // // using declarations:
  564. // //
  565. // // using RefCountedGlobal<YourClass>::FInitOnFirstUse;
  566. // // using RefCountedGlobal<YourClass>::DeinitIfUsed;
  567. // //
  568. // [...]
  569. // };
  570. //
  571. // FInitOnFirstUse() can be called any number of times from any
  572. // thread, including simultaneously from multiple threads, but
  573. // DeinitIfUsed() should only ever be called once, and then
  574. // only when no other threads are calling FInitOnFirstUse().
  575. //
  576. // OnDemandGlobal takes care of tracking whether YourClass was
  577. // ever actually used so that DeinitIfUsed() is safe to call
  578. // even if YourClass was never used (hence the name).
  579. //
  580. // See \cal\src\_davprs\eventlog.cpp for sample usage.
  581. //
  582. template<class _X, class _ParmType = _Empty>
  583. class OnDemandGlobal : private RefCountedGlobal<_X, _ParmType>
  584. {
  585. protected:
  586. //
  587. // Expose access to the single instance of class _X
  588. //
  589. using RefCountedGlobal<_X, _ParmType>::Instance;
  590. //
  591. // Expose operator new and operator delete from
  592. // the Singleton template (via RefCountedGlobal)
  593. // so that they will be used rather than the
  594. // default new and delete to "allocate" space
  595. // for the instance of class _X.
  596. //
  597. using RefCountedGlobal<_X, _ParmType>::operator new;
  598. using RefCountedGlobal<_X, _ParmType>::operator delete;
  599. public:
  600. static BOOL FInitOnFirstUse( const _ParmType& parms )
  601. {
  602. DWORD dwResult = 1;
  603. if ( STATE_INITIALIZED != sm_lState )
  604. {
  605. // Add a reference to the object. If this is the first
  606. // reference, RefCountedGlobal will call _X::FInit()
  607. // to initialize the object.
  608. //
  609. dwResult = DwInitRef( parms );
  610. // If this was not the first reference, then release
  611. // the reference we just added. We only want one
  612. // reference left around by the time DeinitIfUsed()
  613. // so that the DeinitRef() called from there will
  614. // actually destroy the object.
  615. //
  616. if ( dwResult > 1 )
  617. DeinitRef();
  618. }
  619. // Return success/failure (dwResult == 0 --> failure)
  620. //
  621. return !!dwResult;
  622. }
  623. static BOOL FInitOnFirstUse()
  624. {
  625. _Empty e;
  626. return FInitOnFirstUse( e );
  627. }
  628. static VOID DeinitIfUsed()
  629. {
  630. //
  631. // If the object was never initialized (i.e. there was
  632. // never a reference to it), then do nothing.
  633. // Otherwise, deinit the object.
  634. //
  635. if ( FInitialized() )
  636. {
  637. //
  638. // Make sure there is EXACTLY one reference.
  639. // Zero references indicates a bug in setting the
  640. // initialization state. More than one reference
  641. // most likely indicates that OnDemandGlobal is
  642. // being used where RefCountedGlobal is needed.
  643. //
  644. Assert( CRef() == 1 );
  645. DeinitRef();
  646. }
  647. }
  648. };
  649. #endif // _SINGLTON_H_