Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
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 std::call_once instead.
48 **/
49#define ONCE(ONCE_code__)\
50STMT(\
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__)\
66STMT(\
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)\
112STMT(\
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)\
122STMT(\
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)\
132STMT(\
133 free((void*)p); /* if p == 0, free is a no-op */ \
134 (p) = 0;\
135)
136
137#endif // #ifndef INCLUDED_CODE_GENERATION