EPICS Base  7.0.7.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
epicsSingleton.h
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * SPDX-License-Identifier: EPICS
7 * EPICS Base is distributed subject to a Software License Agreement found
8 * in file LICENSE that is included with this distribution.
9 \*************************************************************************/
10 
11 /*
12  * Author: Jeffrey O. Hill
13  */
14 
15 #ifndef epicsSingleton_h
16 #define epicsSingleton_h
17 
18 #include <new>
19 #include <cstddef>
20 
21 #include "libComAPI.h"
22 #include "epicsAssert.h"
23 
25 public:
26  SingletonUntyped () :_pInstance ( 0 ), _refCount ( 0 ) {}
27 # if 0
28  ~SingletonUntyped () {
29  // we don't assert fail on non-zero _refCount
30  // and or non nill _pInstance here because this
31  // is designed to tolerate situations where
32  // file scope epicsSingleton objects (which
33  // theoretically don't have storage lifespan
34  // issues) are deleted in a non-deterministic
35  // order
36  assert ( _refCount == 0 );
37  assert ( _pInstance == 0 );
38  }
39 # endif
40  typedef void * ( * PBuild ) ();
41  LIBCOM_API void incrRefCount ( PBuild );
42  typedef void ( * PDestroy ) ( void * );
43  LIBCOM_API void decrRefCount ( PDestroy );
44  inline void * pInstance () const { return _pInstance; }
45 private:
46  void * _pInstance;
47  std :: size_t _refCount;
49  SingletonUntyped & operator = ( const SingletonUntyped & );
50 };
51 
52 // This class exists for the purpose of avoiding file scope
53 // object chicken and egg problems. It implements thread safe
54 // lazy initialization. To avoid locking overhead retain a
55 // copy of the epicsSingleton :: reference for future use.
56 template < class TYPE >
58 public:
59  class reference {
60  public:
62  :_pSingleton ( & es )
63  {
64  es._singletonUntyped.
65  incrRefCount ( & epicsSingleton < TYPE > :: _build );
66  }
67  reference ( const reference & ref)
68  :_pSingleton ( ref._pSingleton )
69  {
70  assert ( _pSingleton );
71  _pSingleton->_singletonUntyped.
72  incrRefCount ( & epicsSingleton < TYPE > :: _build );
73  }
74  ~reference () {
75  assert ( _pSingleton );
76  _pSingleton->_singletonUntyped.
77  decrRefCount ( & epicsSingleton < TYPE > :: _destroy );
78  }
79  // this somewhat convoluted reference of the return
80  // type ref through the epicsSingleton template is
81  // required for the archaic Tornado gnu compiler
83  operator = ( const reference & ref) {
84  if ( _pSingleton != ref._pSingleton ) {
85  assert ( _pSingleton );
86  _pSingleton->_singletonUntyped.
87  decrRefCount ( epicsSingleton < TYPE > :: _destroy );
88  _pSingleton = ref._pSingleton;
89  assert ( _pSingleton );
90  _pSingleton->_singletonUntyped.
91  incrRefCount ( & epicsSingleton < TYPE > :: _build );
92  }
93  return *this;
94  }
95  TYPE * operator -> () {
96  assert ( _pSingleton );
97  return reinterpret_cast < TYPE * >
98  ( _pSingleton->_singletonUntyped.pInstance () );
99  }
100  const TYPE * operator -> () const {
101  assert ( _pSingleton );
102  return reinterpret_cast < const TYPE * >
103  ( _pSingleton->_singletonUntyped.pInstance () );
104  }
105  TYPE & operator * () {
106  return * this->operator -> ();
107  }
108  const TYPE & operator * () const {
109  return * this->operator -> ();
110  }
111  private:
112  epicsSingleton * _pSingleton;
113  };
114  friend class reference;
115  epicsSingleton () {}
116  // mutex lock/unlock pair overhead incurred
117  // when either of these are called
118  reference getReference () {
119  return reference ( * this );
120  }
121  const reference getReference () const {
122  epicsSingleton < TYPE > * pConstCastAway =
123  const_cast < epicsSingleton < TYPE > * > ( this );
124  return pConstCastAway->getReference ();
125  }
126 private:
127  SingletonUntyped _singletonUntyped;
128  static void * _build () { return new TYPE (); }
129  static void _destroy ( void * pDestroyTypeless) {
130  TYPE * pDestroy =
131  reinterpret_cast < TYPE * > ( pDestroyTypeless );
132  delete pDestroy;
133  }
134  epicsSingleton ( const epicsSingleton & );
135  epicsSingleton & operator = ( const epicsSingleton & );
136 };
137 
138 #endif // epicsSingleton_h
139 
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:71
An EPICS-specific replacement for ANSI C&#39;s assert.