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