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  { \
92  public: \
93  NAME##StaticInit (); \
94  ~NAME##StaticInit (); \
95  NAME##StaticInit (const NAME##StaticInit &) = delete; \
96  NAME##StaticInit &operator=(const NAME##StaticInit &) = delete; \
97  } NAME##Initializer;
98 
99 #define SYSimplementStaticObject(NAME,TYPE) \
100  static int NAME##StaticInitCounter = 0; \
101  static TYPE * NAME = NULL; \
102  NAME##StaticInit::NAME##StaticInit () \
103  { \
104  if (0 == NAME##StaticInitCounter++) \
105  NAME = new TYPE(); \
106  } \
107  NAME##StaticInit::~NAME##StaticInit () \
108  { \
109  if (0 == --NAME##StaticInitCounter) \
110  delete NAME; \
111  }
112 
113 #define SYSdeclareStaticInit(API,NAME) \
114  static class API NAME##StaticInit \
115  { \
116  public: \
117  NAME##StaticInit (); \
118  ~NAME##StaticInit (); \
119  NAME##StaticInit (const NAME##StaticInit &) = delete; \
120  NAME##StaticInit &operator=(const NAME##StaticInit &) = delete; \
121  } NAME##Initializer;
122 
123 #define SYSimplementStaticInit(NAME) \
124  static int NAME##StaticInitCounter = 0; \
125  NAME##StaticInit::NAME##StaticInit () \
126  { \
127  if (0 == NAME##StaticInitCounter++) \
128  NAME##Init(); \
129  } \
130  NAME##StaticInit::~NAME##StaticInit () \
131  { \
132  if (0 == --NAME##StaticInitCounter) \
133  NAME##CleanUp(); \
134  }
135 
136 /// @}
137 
138 /// @brief Class to help deal with the "static initialization order fiasco"
139 ///
140 /// Please see: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14
141 ///
142 /// For example, something like @code
143 /// static UT_SymbolMap<void *> theTable;
144 ///
145 /// void addSymbol(const char *n, void *v) { theTable.addSymbol(n, v); }
146 /// void delSymbol(const char *n) { theTable.deleteSymbol(n);
147 /// @endcode;
148 /// may cause problems if the @c addSymbol() method or the @c delSymbol()
149 /// method are called @b when the table isn't constructed (i.e. before
150 /// construction, after destruction). This can happen if there's another
151 /// static object which has @c addSymbol() or @c delSymbol() in the code path
152 /// of its static destructor.
153 ///
154 /// The way to "fix" this is to use the SYS_StaticInit class @code
155 /// static SYS_StaticInit<UT_SymbolMap<void *>> theTable;
156 ///
157 /// void addSymbol(const char *n, void *v) { theTable->addSymbol(n, v); }
158 /// void delSymbol(const char *n) { theTable->deleteSymbol(n);
159 /// @endcode;
160 /// @note The object will not be destructed (so there will be a memory leak)
161 /// @note The data object is created on first access. This means that it may
162 /// not be 100% thread-safe. Passing @c create == @c true in the
163 /// constructor can cause initial
164 
165 #if defined(__cplusplus)
166  #include "SYS_Types.h"
167 
168  template <typename T>
169  class SYS_StaticInit
170  {
171  public:
172  ///
173  SYS_StaticInit(bool create_on_construction=false)
174  {
175  if (create_on_construction)
176  get();
177  }
178 
179  /// Allocate the object if needed.
180  T *get()
181  {
182  static T *theObject = NULL;
183  if (!theObject)
184  theObject = new T();
185  return theObject;
186  }
187  /// Accessor methods
188  T &operator*() { return *get(); }
189  T *operator->() { return get(); }
190  private:
191  };
192 #endif
193 
194 #endif
IMATH_HOSTDEVICE constexpr Color4< T > operator*(S a, const Color4< T > &v) IMATH_NOEXCEPT
Reverse multiplication: S * Color4.
Definition: ImathColor.h:732