Pyrogenesis  trunk
code_generation.h
Go to the documentation of this file.
1 /* Copyright (c) 2013 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #ifndef INCLUDED_CODE_GENERATION
24 #define INCLUDED_CODE_GENERATION
25 
26 /**
27  * package code into a single statement.
28  *
29  * @param STMT_code__ code to be bundled. (must be interpretable as
30  * a macro argument, i.e. sequence of tokens).
31  * the argument name is chosen to avoid conflicts.
32  *
33  * notes:
34  * - for(;;) { break; } and {} don't work because invocations of macros
35  * implemented with STMT often end with ";", thus breaking if() expressions.
36  * - we'd really like to eliminate "conditional expression is constant"
37  * warnings. replacing 0 literals with extern volatile variables fools
38  * VC7 but isn't guaranteed to be free of overhead. we will just
39  * squelch the warning (unfortunately non-portable).
40  **/
41 #define STMT(STMT_code__) do { STMT_code__; } while(false)
42 
43 /**
44  * execute the code passed as a parameter only the first time this is
45  * reached.
46  * may be called at any time (in particular before main), but is not
47  * thread-safe. if that's important, use pthread_once() instead.
48  **/
49 #define ONCE(ONCE_code__)\
50 STMT(\
51  static bool ONCE_done__ = false;\
52  if(!ONCE_done__)\
53  {\
54  ONCE_done__ = true;\
55  ONCE_code__;\
56  }\
57 )
58 
59 /**
60  * execute the code passed as a parameter except the first time this is
61  * reached.
62  * may be called at any time (in particular before main), but is not
63  * thread-safe.
64  **/
65 #define ONCE_NOT(ONCE_code__)\
66 STMT(\
67  static bool ONCE_done__ = false;\
68  if(!ONCE_done__)\
69  ONCE_done__ = true;\
70  else\
71  ONCE_code__;\
72 )
73 
74 
75 /**
76  * execute the code passed as a parameter before main is entered.
77  *
78  * WARNING: if the source file containing this is not directly referenced
79  * from anywhere, linkers may discard that object file (unless linking
80  * statically). see http://www.cbloom.com/3d/techdocs/more_coding.txt
81  **/
82 #define AT_STARTUP(code__)\
83  namespace { struct UID__\
84  {\
85  UID__() { code__; }\
86  } UID2__; }
87 
88 
89 /**
90  * C++ new wrapper: allocates an instance of the given type and stores a
91  * pointer to it. sets pointer to 0 on allocation failure.
92  *
93  * this simplifies application code when on VC6, which may or
94  * may not throw/return 0 on failure.
95  **/
96 #define SAFE_NEW(type, ptr)\
97  type* ptr;\
98  try\
99  {\
100  ptr = new type();\
101  }\
102  catch(std::bad_alloc&)\
103  {\
104  ptr = 0;\
105  }
106 
107 /**
108  * delete memory ensuing from new and set the pointer to zero
109  * (thus making double-frees safe / a no-op)
110  **/
111 #define SAFE_DELETE(p)\
112 STMT(\
113  delete (p); /* if p == 0, delete is a no-op */ \
114  (p) = 0;\
115 )
116 
117 /**
118  * delete memory ensuing from new[] and set the pointer to zero
119  * (thus making double-frees safe / a no-op)
120  **/
121 #define SAFE_ARRAY_DELETE(p)\
122 STMT(\
123  delete[] (p); /* if p == 0, delete is a no-op */ \
124  (p) = 0;\
125 )
126 
127 /**
128  * free memory ensuing from malloc and set the pointer to zero
129  * (thus making double-frees safe / a no-op)
130  **/
131 #define SAFE_FREE(p)\
132 STMT(\
133  free((void*)p); /* if p == 0, free is a no-op */ \
134  (p) = 0;\
135 )
136 
137 #endif // #ifndef INCLUDED_CODE_GENERATION