EPICS Base  7.0.8.1
 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 #if __cplusplus>=201103L
27  constexpr
28 #endif
29  SingletonUntyped () :_pInstance ( 0 ), _refCount ( 0 ) {}
30 # if 0
31  ~SingletonUntyped () {
32  // we don't assert fail on non-zero _refCount
33  // and or non nill _pInstance here because this
34  // is designed to tolerate situations where
35  // file scope epicsSingleton objects (which
36  // theoretically don't have storage lifespan
37  // issues) are deleted in a non-deterministic
38  // order
39  assert ( _refCount == 0 );
40  assert ( _pInstance == 0 );
41  }
42 # endif
43  typedef void * ( * PBuild ) ();
44  LIBCOM_API void incrRefCount ( PBuild );
45  typedef void ( * PDestroy ) ( void * );
46  LIBCOM_API void decrRefCount ( PDestroy );
47  inline void * pInstance () const { return _pInstance; }
48 private:
49  void * _pInstance;
50  std :: size_t _refCount;
51  SingletonUntyped ( const SingletonUntyped & );
52  SingletonUntyped & operator = ( const SingletonUntyped & );
53 };
54 
55 // This class exists for the purpose of avoiding file scope
56 // object chicken and egg problems. It implements thread safe
57 // lazy initialization. To avoid locking overhead retain a
58 // copy of the epicsSingleton :: reference for future use.
59 template < class TYPE >
61 public:
62  class reference {
63  public:
65  :_pSingleton ( & es )
66  {
67  es._singletonUntyped.
68  incrRefCount ( & epicsSingleton < TYPE > :: _build );
69  }
70  reference ( const reference & ref)
71  :_pSingleton ( ref._pSingleton )
72  {
73  assert ( _pSingleton );
74  _pSingleton->_singletonUntyped.
75  incrRefCount ( & epicsSingleton < TYPE > :: _build );
76  }
77  ~reference () {
78  assert ( _pSingleton );
79  _pSingleton->_singletonUntyped.
80  decrRefCount ( & epicsSingleton < TYPE > :: _destroy );
81  }
82  // this somewhat convoluted reference of the return
83  // type ref through the epicsSingleton template is
84  // required for the archaic Tornado gnu compiler
86  operator = ( const reference & ref) {
87  if ( _pSingleton != ref._pSingleton ) {
88  assert ( _pSingleton );
89  _pSingleton->_singletonUntyped.
90  decrRefCount ( epicsSingleton < TYPE > :: _destroy );
91  _pSingleton = ref._pSingleton;
92  assert ( _pSingleton );
93  _pSingleton->_singletonUntyped.
94  incrRefCount ( & epicsSingleton < TYPE > :: _build );
95  }
96  return *this;
97  }
98  TYPE * operator -> () {
99  assert ( _pSingleton );
100  return reinterpret_cast < TYPE * >
101  ( _pSingleton->_singletonUntyped.pInstance () );
102  }
103  const TYPE * operator -> () const {
104  assert ( _pSingleton );
105  return reinterpret_cast < const TYPE * >
106  ( _pSingleton->_singletonUntyped.pInstance () );
107  }
108  TYPE & operator * () {
109  return * this->operator -> ();
110  }
111  const TYPE & operator * () const {
112  return * this->operator -> ();
113  }
114  private:
115  epicsSingleton * _pSingleton;
116  };
117  friend class reference;
118 #if __cplusplus>=201103L
119  constexpr
120 #endif
121  epicsSingleton () {}
122  // mutex lock/unlock pair overhead incurred
123  // when either of these are called
124  reference getReference () {
125  return reference ( * this );
126  }
127  const reference getReference () const {
128  epicsSingleton < TYPE > * pConstCastAway =
129  const_cast < epicsSingleton < TYPE > * > ( this );
130  return pConstCastAway->getReference ();
131  }
132 private:
133  SingletonUntyped _singletonUntyped;
134  static void * _build () { return new TYPE (); }
135  static void _destroy ( void * pDestroyTypeless) {
136  TYPE * pDestroy =
137  reinterpret_cast < TYPE * > ( pDestroyTypeless );
138  delete pDestroy;
139  }
140  epicsSingleton ( const epicsSingleton & );
141  epicsSingleton & operator = ( const epicsSingleton & );
142 };
143 
144 #endif // epicsSingleton_h
145 
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:71
An EPICS-specific replacement for ANSI C&#39;s assert.