HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SYS_StaticInit.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way withoSYS_StaticInit written permission.
5  *
6  * NAME: SYS_StaticInit.h (SYS Library, C++)
7  *
8  * COMMENTS:
9  * This file contains defines and classes to help with static initializers.
10  */
11 
12 #ifndef __SYS_StaticInit__
13 #define __SYS_StaticInit__
14 
15 /// @{
16 /// Static initializers in C++ are very dangerous and the interactions
17 /// are undefined when one static initializer accesses another statically
18 /// defined object.
19 ///
20 /// These macros allow you to use statically initialized objects safely,
21 /// or, to call a static initialization function at startup. As well, these
22 /// macros handle destruction and cleanup when the last users of your
23 /// code have themselved been destructed.
24 ///
25 /// To avoid name conflicts, you may need to use descriptive names for
26 /// the static objects. Eg for an instance of a UT_Lock class, instead
27 /// of the name theLock choose theSharedStringLock, when it is used in
28 /// UT_SharedString.C
29 ///
30 ///
31 /// HOW TO USE:
32 ///
33 /// FOR OBJECTS:
34 ///
35 /// To have an staticly initialized object that is safe to access from
36 /// other locations during static initialization, do this:
37 ///
38 /// DECLARATION:
39 ///
40 /// // In the header (.h) do this
41 /// SYSdeclareStaticObject(SYS_API,theFoobar);
42 ///
43 /// IMPLEMENTATION
44 ///
45 /// // In the implementation (.C) do this
46 /// SYSimplementStaticObject(theFoobar,SYS_Foobar);
47 ///
48 /// // Then, later you can to
49 /// theFoobar->doStuff();
50 ///
51 ///
52 /// FOR FUNCTIONS
53 ///
54 /// You can also have just plain initialization and cleanup functions.
55 ///
56 /// DECLARATION:
57 ///
58 /// // In the header (.h) do this
59 /// SYSdeclareStaticInit(SYS_API,foobar);
60 ///
61 /// IMPLEMENTATION
62 ///
63 /// // Declare two void functions based on the name you chose
64 /// void foobarInit() {
65 /// // do stuff
66 /// }
67 ///
68 /// void foobarCleanUp() {
69 /// // clean up stuff
70 /// }
71 ///
72 /// // In the implementation (.C) do this
73 /// SYSimplementStaticInit(foobar);
74 ///
75 /// HOW DOES THIS WORK?
76 ///
77 /// This works because a small statically initialized object is inserted
78 /// into each .C file that includes your header. That little object uses
79 /// reference counting to ensure that your static initialization is done
80 /// the first time a .o file that references your code is statically
81 /// initialized.
82 ///
83 /// That reference counting also makes sure that your static stuff is
84 /// cleaned up when all .o's containing references have had their static
85 /// destructors run.
86 ///
87 ///
88 
89 #define SYSdeclareStaticObject(API,NAME) \
90  static class API NAME##StaticInit { \
91  public: \
92  NAME##StaticInit (); \
93  ~NAME##StaticInit (); \
94  NAME##StaticInit (const NAME##StaticInit &) = delete; \
95  NAME##StaticInit &operator=(const NAME##StaticInit &) = delete; \
96  } NAME##Initializer;
97 
98 #define SYSimplementStaticObject(NAME,TYPE) \
99  static int NAME##StaticInitCounter = 0; \
100  static TYPE * NAME = NULL; \
101  NAME##StaticInit::NAME##StaticInit () \
102  { \
103  if (0 == NAME##StaticInitCounter++) \
104  NAME = new TYPE(); \
105  } \
106  NAME##StaticInit::~NAME##StaticInit () \
107  { \
108  if (0 == --NAME##StaticInitCounter) \
109  delete NAME; \
110  }
111 
112 #define SYSdeclareStaticInit(API,NAME) \
113  static class API NAME##StaticInit { \
114  public: \
115  NAME##StaticInit (); \
116  ~NAME##StaticInit (); \
117  NAME##StaticInit (const NAME##StaticInit &) = delete; \
118  NAME##StaticInit &operator=(const NAME##StaticInit &) = delete; \
119  } NAME##Initializer;
120 
121 #define SYSimplementStaticInit(NAME) \
122  static int NAME##StaticInitCounter = 0; \
123  NAME##StaticInit::NAME##StaticInit () \
124  { \
125  if (0 == NAME##StaticInitCounter++) \
126  NAME##Init(); \
127  } \
128  NAME##StaticInit::~NAME##StaticInit () \
129  { \
130  if (0 == --NAME##StaticInitCounter) \
131  NAME##CleanUp(); \
132  }
133 
134 /// @}
135 
136 /// @brief Class to help deal with the "static initialization order fiasco"
137 ///
138 /// Please see: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14
139 ///
140 /// For example, something like @code
141 /// static UT_SymbolMap<void *> theTable;
142 ///
143 /// void addSymbol(const char *n, void *v) { theTable.addSymbol(n, v); }
144 /// void delSymbol(const char *n) { theTable.deleteSymbol(n);
145 /// @endcode;
146 /// may cause problems if the @c addSymbol() method or the @c delSymbol()
147 /// method are called @b when the table isn't constructed (i.e. before
148 /// construction, after destruction). This can happen if there's another
149 /// static object which has @c addSymbol() or @c delSymbol() in the code path
150 /// of its static destructor.
151 ///
152 /// The way to "fix" this is to use the SYS_StaticInit class @code
153 /// static SYS_StaticInit<UT_SymbolMap<void *>> theTable;
154 ///
155 /// void addSymbol(const char *n, void *v) { theTable->addSymbol(n, v); }
156 /// void delSymbol(const char *n) { theTable->deleteSymbol(n);
157 /// @endcode;
158 /// @note The object will not be destructed (so there will be a memory leak)
159 /// @note The data object is created on first access. This means that it may
160 /// not be 100% thread-safe. Passing @c create == @c true in the
161 /// constructor can cause initial
162 
163 #if defined(__cplusplus)
164  #include "SYS_Types.h"
165 
166  template <typename T>
167  class SYS_StaticInit {
168  public:
169  ///
170  SYS_StaticInit(bool create_on_construction=false)
171  {
172  if (create_on_construction)
173  get();
174  }
175 
176  /// Allocate the object if needed.
177  T *get()
178  {
179  static T *theObject = NULL;
180  if (!theObject)
181  theObject = new T();
182  return theObject;
183  }
184  /// Accessor methods
185  T &operator*() { return *get(); }
186  T *operator->() { return get(); }
187  private:
188  };
189 #endif
190 
191 #endif
IMATH_HOSTDEVICE constexpr Color4< T > operator*(S a, const Color4< T > &v) IMATH_NOEXCEPT
Reverse multiplication: S * Color4.
Definition: ImathColor.h:732