PTLib Version 2.12.9

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
object.h
Go to the documentation of this file.
1 /*
2 * object.h
3 *
4 * Mother of all ancestor classes.
5 *
6 * Portable Tools Library
7 *
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is Portable Windows Library.
21 *
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23 *
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
26 *
27 * Contributor(s): ______________________________________.
28 *
29 * $Revision: 30928 $
30 * $Author: rjongbloed $
31 * $Date: 2013-11-20 10:39:04 +1100 (Wed, 20 Nov 2013) $
32 */
33
34 #ifndef PTLIB_OBJECT_H
35 #define PTLIB_OBJECT_H
36
37 #ifdef P_USE_PRAGMA
38 #pragma interface
39 #endif
40
41 #if defined(_WIN32)
42 #include "msos/ptlib/platform.h"
43 #else
44 #include "unix/ptlib/platform.h"
45 #endif
46
47 #include <stdio.h>
48 #include <stdarg.h>
49 #include <stdlib.h>
50 #include <limits.h>
51 #include <string.h>
52 #include <ctype.h>
53 #include <errno.h>
54
55 #include <string>
56 #include <iomanip>
57 #include <iostream>
58 #include <sstream>
59 #include <vector>
60 #include <list>
61 #include <map>
62 #include <algorithm>
63 #include <typeinfo>
64
65 using namespace std; // Not a good practice (name space polution), but will take too long to fix.
66
67 // Somewhere in C headers you get this, which blows up STL version
68 #ifdef min
69 #undef min
70 #endif
71 #ifdef max
72 #undef max
73 #endif
74
75
77
78 #define P_REMOVE_VIRTUAL_INTERNAL_BASE(fn) __inline virtual struct ptlib_virtual_function_changed_or_removed ****** fn { return 0; }
79
80 #if defined(_MSC_VER)
81 #if _MSC_VER < 1310
82 #define P_DEPRECATED
83 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
84 #elif _MSC_VER < 1400
85 #define P_DEPRECATED __declspec(deprecated)
86 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated) type fn body
87 #else
88 #define P_DEPRECATED __declspec(deprecated)
89 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __inline virtual __declspec(deprecated("Virtual function signature changed or function deprecated")) type fn body
90 #endif
91 #elif defined(__GNUC__)
92 #if __GNUC__ < 4
93 #define P_DEPRECATED
94 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
95 #else
96 #define P_DEPRECATED __attribute__((deprecated))
97 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) __attribute__((warn_unused_result)) __attribute__((deprecated)) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
98 #endif
99 #else
100 #define P_DEPRECATED
101 #define P_REMOVE_VIRTUAL_INTERNAL(type, fn, body) P_REMOVE_VIRTUAL_INTERNAL_BASE(fn)
102 #endif
103
104 #define P_REMOVE_VIRTUAL_VOID(fn) P_REMOVE_VIRTUAL_INTERNAL(void, fn, {})
105 #define P_REMOVE_VIRTUAL(type, fn, ret) P_REMOVE_VIRTUAL_INTERNAL(type, fn, { return ret; })
106
107
108 #ifdef _MSC_VER
109 #define P_PUSH_MSVC_WARNINGS(warnings) __pragma(warning(push)) __pragma(warning(disable:warnings))
110 #define P_POP_MSVC_WARNINGS() __pragma(warning(pop))
111 #else
112 #define P_PUSH_MSVC_WARNINGS(warnings)
113 #define P_POP_MSVC_WARNINGS()
114 #endif // _MSC_VER
115 #define P_DISABLE_MSVC_WARNINGS(warnings, statement) P_PUSH_MSVC_WARNINGS(warnings) statement P_POP_MSVC_WARNINGS()
116
117
118 // P_USE_INTEGER_BOOL is the default and gives the old behaviour (it
119 // is also used for C translation units).
120 // without P_USE_INTEGER_BOOL, the ANSI C++ bool is used.
121
122 #ifndef FALSE
123 #define FALSE 0
124 #endif
125 #ifndef TRUE
126 #define TRUE 1
127 #endif
128
129 #if defined(P_USE_INTEGER_BOOL) || !defined(__cplusplus)
130 typedef BOOL PBoolean;
131 #define PTrue TRUE
132 #define PFalse FALSE
133 #else
134 typedef bool PBoolean;
135 #define PTrue true
136 #define PFalse false
137 #endif
138
139
141 // Disable inlines when debugging for faster compiles (the compiler doesn't
142 // actually inline the function with debug on any way).
143
144 #ifndef P_USE_INLINES
145 #ifdef _DEBUG
146 #define P_USE_INLINES 0
147 #else
148 #define P_USE_INLINES 0
149 #endif
150 #endif
151
152 #if P_USE_INLINES
153 #define PINLINE __inline
154 #else
155 #define PINLINE
156 #endif
157
158
160 // Handy macros
161
163 #define PARG_COUNT(...) PARG_COUNT_PART1(PARG_COUNT_PART2(__VA_ARGS__,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
164 #define PARG_COUNT_PART1(arg) arg
165 #define PARG_COUNT_PART2(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,N,...) N
166
168 #define P_STRINGISE(v) P_STRINGISE_PART2(v)
169 #define P_STRINGIZE(v) P_STRINGISE_PART2(v)
170 #define P_STRINGISE_PART2(v) #v
171
183 #define P_DECLARE_ENUM_EX(name, countName, firstName, firstValue, ...) \
184 enum name { firstName = firstValue, Begin##name = firstName, __VA_ARGS__, End##name, countName = End##name-Begin##name }; \
185 friend __inline name operator++(name & e ) { PAssert(e < End##name, PInvalidParameter); return e = (name)(e+1); } \
186 friend __inline name operator++(name & e, int) { PAssert(e < End##name, PInvalidParameter); name o=e; e = (name)(e+1); return o; } \
187 friend __inline name operator--(name & e ) { PAssert(e >= Begin##name, PInvalidParameter); return e = (name)(e-1); } \
188 friend __inline name operator--(name & e, int) { PAssert(e >= Begin##name, PInvalidParameter); name o=e; e = (name)(e-1); return o; } \
189 static __inline name name##FromInt(int v) { return (name)(v < Begin##name ? Begin##name : v >= End##name ? (End##name-1) : v); }
190
202 #define P_DECLARE_ENUM(name, first, ...) P_DECLARE_ENUM_EX(name, Num##name, first, 0, __VA_ARGS__)
203
204 extern void PPrintEnum(std::ostream & strm, int e, int begin, int end, char const * const * names);
205 extern int PReadEnum(std::istream & strm, int begin, int end, char const * const * names);
206
207 #define P_ENUM_NAMES_PART1(narg, args)P_ENUM_NAMES_PART2(narg, args)
208 #define P_ENUM_NAMES_PART2(narg, args) P_ENUM_NAMES_ARG_##narg args
209 #define P_ENUM_NAMES_ARG_1(_1 )#_1
210 #define P_ENUM_NAMES_ARG_2(_1,_2 )#_1,#_2
211 #define P_ENUM_NAMES_ARG_3(_1,_2,_3 )#_1,#_2,#_3
212 #define P_ENUM_NAMES_ARG_4(_1,_2,_3,_4 )#_1,#_2,#_3,#_4
213 #define P_ENUM_NAMES_ARG_5(_1,_2,_3,_4,_5 )#_1,#_2,#_3,#_4,#_5
214 #define P_ENUM_NAMES_ARG_6(_1,_2,_3,_4,_5,_6 )#_1,#_2,#_3,#_4,#_5,#_6
215 #define P_ENUM_NAMES_ARG_7(_1,_2,_3,_4,_5,_6,_7 )#_1,#_2,#_3,#_4,#_5,#_6,#_7
216 #define P_ENUM_NAMES_ARG_8(_1,_2,_3,_4,_5,_6,_7,_8 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8
217 #define P_ENUM_NAMES_ARG_9(_1,_2,_3,_4,_5,_6,_7,_8,_9 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9
218 #define P_ENUM_NAMES_ARG_10(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10
219 #define P_ENUM_NAMES_ARG_11(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11
220 #define P_ENUM_NAMES_ARG_12(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12
221 #define P_ENUM_NAMES_ARG_13(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13
222 #define P_ENUM_NAMES_ARG_14(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14
223 #define P_ENUM_NAMES_ARG_15(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15
224 #define P_ENUM_NAMES_ARG_16(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16
225 #define P_ENUM_NAMES_ARG_17(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17
226 #define P_ENUM_NAMES_ARG_18(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18
227 #define P_ENUM_NAMES_ARG_19(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19
228 #define P_ENUM_NAMES_ARG_20(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20
229 #define P_ENUM_NAMES_ARG_21(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21
230 #define P_ENUM_NAMES_ARG_22(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22
231 #define P_ENUM_NAMES_ARG_23(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23
232 #define P_ENUM_NAMES_ARG_24(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24
233 #define P_ENUM_NAMES_ARG_25(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25
234 #define P_ENUM_NAMES_ARG_26(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26
235 #define P_ENUM_NAMES_ARG_27(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27
236 #define P_ENUM_NAMES_ARG_28(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28
237 #define P_ENUM_NAMES_ARG_29(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29
238 #define P_ENUM_NAMES_ARG_30(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30
239 #define P_ENUM_NAMES_ARG_31(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31
240 #define P_ENUM_NAMES_ARG_32(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32
241 #define P_ENUM_NAMES_ARG_33(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33
242 #define P_ENUM_NAMES_ARG_34(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34
243 #define P_ENUM_NAMES_ARG_35(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35
244 #define P_ENUM_NAMES_ARG_36(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35,#_36
245 #define P_ENUM_NAMES_ARG_37(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35,#_36,#_37
246 #define P_ENUM_NAMES_ARG_38(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35,#_36,#_37,#_38
247 #define P_ENUM_NAMES_ARG_39(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39 )#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35,#_36,#_37,#_38,#_39
248 #define P_ENUM_NAMES_ARG_40(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40)#_1,#_2,#_3,#_4,#_5,#_6,#_7,#_8,#_9,#_10,#_11,#_12,#_13,#_14,#_15,#_16,#_17,#_18,#_19,#_20,#_21,#_22,#_23,#_24,#_25,#_26,#_27,#_28,#_29,#_30,#_31,#_32,#_33,#_34,#_35,#_36,#_37,#_38,#_39,#_40
249
251 #define P_DECLARE_STREAMABLE_ENUM_EX(name, countName, firstName, firstValue, ...) \
252 P_DECLARE_ENUM_EX(name, countName, firstName, firstValue, __VA_ARGS__) \
253 struct PEnumNames_##name { \
254 static char const * const * Names() { static char const * const Strings[] = \
255 { #firstName, P_ENUM_NAMES_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__)) }; return Strings; } \
256 }; \
257 friend __inline std::ostream & operator<<(std::ostream & strm, name e) \
258 { PPrintEnum(strm, e, Begin##name, End##name, PEnumNames_##name::Names()); return strm; } \
259 friend __inline std::istream & operator>>(std::istream & strm, name & e) \
260 { e = (name)PReadEnum(strm, Begin##name, End##name, PEnumNames_##name::Names()); return strm; } \
261
262
263 #define P_DECLARE_STREAMABLE_ENUM(name, first, ...) P_DECLARE_STREAMABLE_ENUM_EX(name, Num##name, first, 0, __VA_ARGS__)
264
265
267 // Declare the debugging support
268
269 #ifndef P_USE_ASSERTS
270 #define P_USE_ASSERTS 1
271 #endif
272
273 #if !P_USE_ASSERTS
274
275 #define PAssert(b, m) (b)
276 #define PAssert2(b, c, m) (b)
277 #define PAssertOS(b) (b)
278 #define PAssertNULL(p) (p)
279 #define PAssertAlways(m) {}
280 #define PAssertAlways2(c, m) {}
281
282 #else // P_USE_ASSERTS
283
285 enum PStandardAssertMessage {
286 PLogicError,
287 POutOfMemory,
288 PNullPointerReference,
289 PInvalidCast,
290 PInvalidArrayIndex,
291 PInvalidArrayElement,
292 PStackEmpty,
293 PUnimplementedFunction,
294 PInvalidParameter,
295 POperatingSystemError,
296 PChannelNotOpen,
297 PUnsupportedFeature,
298 PInvalidWindow,
299 PMaxStandardAssertMessage
300 };
301
302 #define __CLASS__ NULL
303
304 bool PAssertFunc(const char * file, int line, const char * className, PStandardAssertMessage msg);
305 bool PAssertFunc(const char * file, int line, const char * className, const char * msg);
306 bool PAssertFunc(const char * full_msg);
307
308
315 #define PAssert(b, msg) ((b)?true:PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg)))
316
324 #define PAssert2(b, cls, msg) ((b)?true:PAssertFunc(__FILE__,__LINE__,(cls),(msg)))
325
332 #define PAssertOS(b) ((b)?true:PAssertFunc(__FILE__,__LINE__,__CLASS__,POperatingSystemError))
333
343 #define PAssertNULL(ptr) (((ptr)!=NULL)?(ptr): \
344 (PAssertFunc(__FILE__,__LINE__, __CLASS__, PNullPointerReference),(ptr)))
345
352 #define PAssertAlways(msg) PAssertFunc(__FILE__,__LINE__,__CLASS__,(msg))
353
360 #define PAssertAlways2(cls, msg) PAssertFunc(__FILE__,__LINE__,(cls),(msg))
361
362 #endif // P_USE_ASSERTS
363
364
369 ostream & PGetErrorStream();
370
374 void PSetErrorStream(ostream * strm );
375
390 #define PError (PGetErrorStream())
391
392
394 // Debug and tracing
395
396 #ifndef PTRACING
397 #define PTRACING 2
398 #endif
399
400 #if PTRACING
401
402 class PObject;
403 class PArgList;
404
417 class PTrace
418 {
419 public:
421 enum Options {
422 Blocks = 0x0001,
427 DateAndTime = 0x0002,
428 Timestamp = 0x0004,
429 Thread = 0x0008,
430 TraceLevel = 0x0010,
431 FileAndLine = 0x0020,
432 ThreadAddress = 0x0040,
433 AppendToFile = 0x0080,
434 GMTTime = 0x0100,
435 RotateDaily = 0x0200,
436 RotateHourly = 0x0400,
437 RotateMinutely = 0x0800,
438 RotateLogMask = RotateDaily + RotateHourly + RotateMinutely,
440 ObjectInstance = 0x1000,
441 ContextIdentifier = 0x2000,
442 SystemLogStream = 0x8000
445 };
446
447
448 #define PTRACE_ARGLIST_OPT_HELP \
449 "use +X or -X to add/remove option where X is one of:\r" \
450 " block PTrace::Block constructs in output\r" \
451 " time time since prgram start\r" \
452 " date date and time\r" \
453 " gmt Date/time is in UTC\r" \
454 " thread thread name and identifier\r" \
455 " level log level\r" \
456 " file source file name and line number\r" \
457 " object PObject pointer\r" \
458 " context context identifier\r" \
459 " daily rotate output file daily\r" \
460 " hour rotate output file hourly\r" \
461 " minute rotate output file every minute\r" \
462 " append append to output file, otherwise overwrites"
463
464 #define PTRACE_ARGLIST \
465 "t-trace. Trace enable (use multiple times for more detail)\n" \
466 "o-output: Specify filename for trace output\n" \
467 "-trace-option: Specify trace option(s),\r" PTRACE_ARGLIST_OPT_HELP "\n" \
468 "-trace-rollover: Specify trace file rollover file name pattern\n"
469
470 #define PTRACE_INITIALISE(...) PTrace::Initialise(__VA_ARGS__)
471
475 static void Initialise(
476 const PArgList & args,
477 unsigned options =
478 #ifdef _DEBUG
479 FileAndLine |
480 #endif
481 Timestamp | Thread | Blocks,
482 const char * traceLevel = "trace",
483 const char * outputFile = "output",
484 const char * traceOpts = "trace-option",
485 const char * traceRollover = "trace-rollover"
486 );
487
519 static void Initialise(
520 unsigned level,
521 const char * filename = NULL,
522 unsigned options = Timestamp | Thread | Blocks,
523 const char * rolloverPattern = NULL
524 );
525
526 // Deprecated - for backward compatibility
527 static void Initialise(
528 unsigned level,
529 const char * filename,
530 const char * rolloverPattern,
531 unsigned options = Timestamp | Thread | Blocks
532 ) { Initialise(level, filename, options, rolloverPattern); }
533
540 static void SetOptions(
541 unsigned options
542 );
543
552 static void ClearOptions(
553 unsigned options
554 );
555
561 static unsigned GetOptions();
562
568 static void SetLevel(
569 unsigned level
570 );
571
577 static unsigned GetLevel();
578
583 static PBoolean CanTrace(
584 unsigned level
585 );
586
591 static void SetStream(
592 ostream * out
593 );
594
597 static ostream * GetStream();
598
614 static ostream & Begin(
615 unsigned level,
616 const char * fileName,
617 int lineNum,
618 const PObject * instance = NULL,
619 const char * module = NULL
620 );
621
622 static ostream & Begin(
623 unsigned level,
624 const char * fileName,
625 int lineNum,
626 const char * module,
627 const PObject * instance,
628 const char * defModule
629 ) { return Begin(level, fileName, lineNum, instance, module != NULL ? module : defModule); }
630
631 static ostream & Begin(
632 unsigned level,
633 const char * fileName,
634 int lineNum,
635 const PObject * instance,
636 const PObject * defInstance,
637 const char * module
638 ) { return Begin(level, fileName, lineNum, instance != NULL ? instance : defInstance, module); }
639
657 static ostream & End(
658 ostream & strm
659 );
660
666 class Block {
667 public:
669 Block(
670 const char * fileName,
671 int lineNum,
672 const char * traceName
674 );
675 Block(const Block & obj)
676 : file(obj.file), line(obj.line), name(obj.name) { }
678 ~Block();
679 private:
680 Block & operator=(const Block &)
681 { return *this; }
682 const char * file;
683 int line;
684 const char * name;
685 };
686
687 static unsigned GetNextContextIdentifier();
688 };
689
690 /* Macro to conditionally declare a parameter to a function to avoid compiler
691 warning due that parameter only being used in a <code>PTRACE()</code> */
692 #define PTRACE_PARAM(...) __VA_ARGS__
693
700 #define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
701
705 #define PTRACE_LINE() \
706 if (PTrace::CanTrace(1)) \
707 PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End; \
708 else (void)0
709
710
711
712 #define PTRACE_INTERNAL(level, condition, args, ...) \
713 if (PTrace::CanTrace(level) condition) \
714 PTrace::Begin(level, __FILE__, __LINE__, __VA_ARGS__) << args << PTrace::End; \
715 else (void)0
716
717 #define PTRACE_NO_CONDITION
718
719
720 #define PTRACE_PART1(narg, args) PTRACE_PART2(narg, args)
721 #define PTRACE_PART2(narg, args) PTRACE_ARG_##narg args
722
723 #define PTRACE_ARG_4(level, object, module, args) \
724 PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, object, module)
725
726 #define PTRACE_ARG_3(level, objectOrModule, args) \
727 PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, objectOrModule, PTraceObjectInstance(objectOrModule), PTraceModule())
728
729 #define PTRACE_ARG_2(level, args) \
730 PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, PTraceObjectInstance(), PTraceModule())
731
732
733 #define PTRACE_IF_PART1(narg, args) PTRACE_IF_PART2(narg, args)
734 #define PTRACE_IF_PART2(narg, args) PTRACE_IF_ARG_##narg args
735
736 #define PTRACE_IF_ARG_5(level, condition, object, module, args) \
737 PTRACE_INTERNAL(level, && (condition), args, object, module)
738
739 #define PTRACE_IF_ARG_4(level, condition, objectOrModule, args) \
740 PTRACE_INTERNAL(level, && (condition), args, objectOrModule, PTraceObjectInstance(objectOrModule), PTraceModule())
741
742 #define PTRACE_IF_ARG_3(level, condition, args) \
743 PTRACE_INTERNAL(level, && (condition), args, PTraceObjectInstance(), PTraceModule())
744
745
746 #define PTRACE_BEGIN_PART1(narg, args) PTRACE_BEGIN_PART2(narg, args)
747 #define PTRACE_BEGIN_PART2(narg, args) PTRACE_BEGIN_ARG_##narg args
748
749 #define PTRACE_BEGIN_ARG_3(level, object, module) \
750 PTrace::Begin(level, __FILE__, __LINE__, object, module)
751
752 #define PTRACE_BEGIN_ARG_2(level, objectOrModule) \
753 PTrace::Begin(level, __FILE__, __LINE__, objectOrModule, PTraceObjectInstance(objectOrModule), PTraceModule())
754
755 #define PTRACE_BEGIN_ARG_1(level) \
756 PTrace::Begin(level, __FILE__, __LINE__, PTraceObjectInstance(), PTraceModule())
757
758
759 // Backward compatibility
760 #define PTRACE2(level, object, args) \
761 PTRACE_INTERNAL(level, PTRACE_NO_CONDITION, args, object, PTraceModule())
762 #define PTRACE_IF2(level, condition, object, args) \
763 PTRACE_INTERNAL(level, && (condition), args, object, PTraceModule())
764
790 #define PTRACE(...) PTRACE_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__))
791
804 #define PTRACE_IF(...) PTRACE_IF_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__))
805
815 #define PTRACE_BEGIN(...) PTRACE_BEGIN_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__))
816
817
818 __inline const PObject * PTraceObjectInstance() { return NULL; }
819 __inline static const PObject * PTraceObjectInstance(const void *) { return NULL; }
820 __inline const char * PTraceModule() { return NULL; }
821
822
823 #if PTRACING==2
824
830 #define PTRACE_CONTEXT_ID_NEW() SetTraceContextIdentifier(PTrace::GetNextContextIdentifier())
831 #define PTRACE_CONTEXT_ID_SET(to, from) (to).SetTraceContextIdentifier(from)
832 #define PTRACE_CONTEXT_ID_FROM(obj) SetTraceContextIdentifier(obj)
833 #define PTRACE_CONTEXT_ID_TO(obj) GetTraceContextIdentifier(obj)
834
835 class PTraceSaveContextIdentifier
836 {
837 private:
838 class PThread * m_currentThread;
839 unsigned m_savedContextIdentifier;
840 public:
841 PTraceSaveContextIdentifier(const PObject & obj);
842 PTraceSaveContextIdentifier(const PObject * obj);
843 ~PTraceSaveContextIdentifier();
844 };
845
846 #define PTRACE_CONTEXT_ID_PUSH_THREAD(obj) PTraceSaveContextIdentifier praceSavedContextIdentifier(obj)
847
848 #endif // PTRACING==2
849
850
851 #define P_DECLARE_TRACED_ENUM P_DECLARE_STREAMABLE_ENUM
852 #define P_DECLARE_TRACED_ENUM_EX P_DECLARE_STREAMABLE_ENUM_EX
853
854 #endif // PTRACING
855
856 #ifndef PTRACE_ARGLIST
857 #define PTRACE_ARGLIST
858 #endif
859
860 #ifndef PTRACE_INITIALISE
861 #define PTRACE_INITIALISE(...)
862 #endif
863
864 #ifndef PTRACE_PARAM
865 #define PTRACE_PARAM(...)
866 #endif
867
868 #ifndef PTRACE_BLOCK
869 #define PTRACE_BLOCK(n)
870 #endif
871
872 #ifndef PTRACE_LINE
873 #define PTRACE_LINE()
874 #endif
875
876 #ifndef PTRACE
877 #define PTRACE(...)
878 #endif
879
880 #ifndef PTRACE_IF
881 #define PTRACE_IF(...)
882 #endif
883
884 #ifndef PTRACE_BEGIN
885 #define PTRACE_BEGIN(...)
886 #endif
887
888 #ifndef PTRACE2
889 #define PTRACE2(level, obj, arg)
890 #endif
891
892 #ifndef PTRACE_IF2
893 #define PTRACE_IF2(level, cond, obj, args)
894 #endif
895
896 #ifndef PTRACE_CONTEXT_ID_NEW
897 #define PTRACE_CONTEXT_ID_NEW()
898 #endif
899
900 #ifndef PTRACE_CONTEXT_ID_SET
901 #define PTRACE_CONTEXT_ID_SET(to, from)
902 #endif
903
904 #ifndef PTRACE_CONTEXT_ID_FROM
905 #define PTRACE_CONTEXT_ID_FROM(obj)
906 #endif
907
908 #ifndef PTRACE_CONTEXT_ID_TO
909 #define PTRACE_CONTEXT_ID_TO(obj)
910 #endif
911
912 #ifndef PTRACE_CONTEXT_ID_PUSH_THREAD
913 #define PTRACE_CONTEXT_ID_PUSH_THREAD(obj)
914 #endif
915
916 #ifndef P_DECLARE_TRACED_ENUM
917 #define P_DECLARE_TRACED_ENUM P_DECLARE_ENUM
918 #endif
919
920 #ifndef P_DECLARE_TRACED_ENUM_EX
921 #define P_DECLARE_TRACED_ENUM_EX P_DECLARE_ENUM_EX
922 #endif
923
924
925 #if PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE))
926
927 #define PMEMORY_HEAP 1
928
935 class PMemoryHeap {
936 protected:
938 PMemoryHeap();
939
940 public:
941 // Clear up the memory checking subsystem, dumping memory leaks.
942 ~PMemoryHeap();
943
950 static void * Allocate(
951 size_t nSize,
952 const char * file,
953 int line,
954 const char * className
955 );
962 static void * Allocate(
963 size_t count,
964 size_t iSize,
965 const char * file,
966 int line
967 );
968
976 static void * Reallocate(
977 void * ptr,
978 size_t nSize,
979 const char * file,
980 int line
981 );
982
988 static void Deallocate(
989 void * ptr,
990 const char * className
991 );
992
995 enum Validation {
996 Ok, Bad, Trashed
997 };
1005 static Validation Validate(
1006 const void * ptr,
1007 const char * className,
1008 ostream * error
1009 );
1010
1015 static PBoolean ValidateHeap(
1016 ostream * error = NULL
1017 );
1018
1024 static PBoolean SetIgnoreAllocations(
1025 PBoolean ignore
1026 );
1027
1031 static void DumpStatistics();
1035 static void DumpStatistics(ostream & strm );
1036
1037 #if PMEMORY_CHECK
1038 struct State {
1039 DWORD allocationNumber;
1040 };
1041 #else
1042 typedef _CrtMemState State;
1043 #endif
1044
1045 /* Get memory state.
1046 This returns a state that may be used to determine where to start dumping
1047 objects from.
1048 */
1049 static void GetState(
1050 State & state
1051 );
1052
1060 static void DumpObjectsSince(
1061 const State & when
1062 );
1063
1069 static void DumpObjectsSince(
1070 const State & when,
1071 ostream & strm
1072 );
1073
1079 static void SetAllocationBreakpoint(
1080 DWORD point
1081 );
1082
1083 #if PMEMORY_CHECK
1084
1085 protected:
1086 void * InternalAllocate(
1087 size_t nSize, // Number of bytes to allocate.
1088 const char * file, // Source file name for allocating function.
1089 int line, // Source file line for allocating function.
1090 const char * className // Class name for allocating function.
1091 );
1092 Validation InternalValidate(
1093 const void * ptr, // Pointer to memory block to check
1094 const char * className, // Class name it should be.
1095 ostream * error // Stream to receive error message (may be NULL)
1096 );
1097 void InternalDumpStatistics(ostream & strm);
1098 void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
1099
1100 class Wrapper {
1101 public:
1102 Wrapper();
1103 ~Wrapper();
1104 PMemoryHeap * operator->() const { return instance; }
1105 private:
1106 PMemoryHeap * instance;
1107 };
1108 friend class Wrapper;
1109
1110 enum Flags {
1111 NoLeakPrint = 1
1112 };
1113
1114 #pragma pack(1)
1115 struct Header {
1116 enum {
1117 // Assure that the Header struct is aligned to 8 byte boundary
1118 NumGuardBytes = 16 - (sizeof(Header *) +
1119 sizeof(Header *) +
1120 sizeof(const char *) +
1121 sizeof(const char *) +
1122 sizeof(size_t) +
1123 sizeof(DWORD) +
1124 sizeof(WORD) +
1125 sizeof(BYTE) +
1126 sizeof(PThreadIdentifier)
1127 )%8
1128 };
1129
1130 Header * prev;
1131 Header * next;
1132 const char * className;
1133 const char * fileName;
1134 size_t size;
1135 DWORD request;
1136 WORD line;
1137 BYTE flags;
1138 PThreadIdentifier threadId;
1139 char guard[NumGuardBytes];
1140
1141 static char GuardBytes[NumGuardBytes];
1142 };
1143 #pragma pack()
1144
1145 PBoolean isDestroyed;
1146
1147 Header * listHead;
1148 Header * listTail;
1149
1150 static DWORD allocationBreakpoint;
1151 DWORD allocationRequest;
1152 DWORD firstRealObject;
1153 BYTE flags;
1154
1155 char allocFillChar;
1156 char freeFillChar;
1157
1158 DWORD currentMemoryUsage;
1159 DWORD peakMemoryUsage;
1160 DWORD currentObjects;
1161 DWORD peakObjects;
1162 DWORD totalObjects;
1163
1164 ostream * leakDumpStream;
1165
1166 #if defined(_WIN32)
1167 CRITICAL_SECTION mutex;
1168 #elif defined(P_PTHREADS)
1169 pthread_mutex_t mutex;
1170 #elif defined(P_VXWORKS)
1171 void * mutex;
1172 #endif
1173
1174 #else
1175
1176 static void CreateInstance();
1177 #define P_CLIENT_BLOCK (_CLIENT_BLOCK|(0x61<<16)) // This identifies a PObject derived class
1178 _CrtMemState initialState;
1179
1180 #endif // PMEMORY_CHECK
1181 };
1182
1183
1188 inline void * runtime_malloc(size_t bytes ) { return malloc(bytes); }
1189
1194 inline void runtime_free(void * ptr ) { free(ptr); }
1195
1196
1203 #define malloc(s) PMemoryHeap::Allocate(s, __FILE__, __LINE__, NULL)
1204
1211 #define calloc(n,s) PMemoryHeap::Allocate(n, s, __FILE__, __LINE__)
1212
1219 #define realloc(p,s) PMemoryHeap::Reallocate(p, s, __FILE__, __LINE__)
1220
1221
1228 #define free(p) PMemoryHeap::Deallocate(p, NULL)
1229
1230
1237 #define cfree(p) PMemoryHeap::Deallocate(p, NULL)
1238
1239
1254 #define PNEW new (__FILE__, __LINE__)
1255
1256 #if !defined(_MSC_VER) || _MSC_VER<1200
1257 #define PSPECIAL_DELETE_FUNCTION
1258 #else
1259 #define PSPECIAL_DELETE_FUNCTION \
1260 void operator delete(void * ptr, const char *, int) \
1261 { PMemoryHeap::Deallocate(ptr, Class()); } \
1262 void operator delete[](void * ptr, const char *, int) \
1263 { PMemoryHeap::Deallocate(ptr, Class()); }
1264 #endif
1265
1266 #define PNEW_AND_DELETE_FUNCTIONS \
1267 void * operator new(size_t nSize, const char * file, int line) \
1268 { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
1269 void * operator new(size_t nSize) \
1270 { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
1271 void operator delete(void * ptr) \
1272 { PMemoryHeap::Deallocate(ptr, Class()); } \
1273 void * operator new(size_t, void * placement) \
1274 { return placement; } \
1275 void operator delete(void *, void *) \
1276 { } \
1277 void * operator new[](size_t nSize, const char * file, int line) \
1278 { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
1279 void * operator new[](size_t nSize) \
1280 { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
1281 void operator delete[](void * ptr) \
1282 { PMemoryHeap::Deallocate(ptr, Class()); } \
1283 PSPECIAL_DELETE_FUNCTION
1284
1285
1286 inline void * operator new(size_t nSize, const char * file, int line)
1287 { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
1288
1289 inline void * operator new[](size_t nSize, const char * file, int line)
1290 { return PMemoryHeap::Allocate(nSize, file, line, NULL); }
1291
1292 #ifndef __GNUC__
1293 void * operator new(size_t nSize);
1294 void * operator new[](size_t nSize);
1295
1296 void operator delete(void * ptr);
1297 void operator delete[](void * ptr);
1298
1299 #if defined(_MSC_VER) && _MSC_VER>=1200
1300 inline void operator delete(void * ptr, const char *, int)
1301 { PMemoryHeap::Deallocate(ptr, NULL); }
1302
1303 inline void operator delete[](void * ptr, const char *, int)
1304 { PMemoryHeap::Deallocate(ptr, NULL); }
1305 #endif
1306 #endif
1307
1308
1309 class PMemoryHeapIgnoreAllocationsForScope {
1310 public:
1311 PMemoryHeapIgnoreAllocationsForScope() : previousIgnoreAllocations(PMemoryHeap::SetIgnoreAllocations(true)) { }
1312 ~PMemoryHeapIgnoreAllocationsForScope() { PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations); }
1313 private:
1314 PBoolean previousIgnoreAllocations;
1315 };
1316
1317 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE PMemoryHeapIgnoreAllocationsForScope instance_PMemoryHeapIgnoreAllocationsForScope
1318
1319 class PMemoryAllocationBreakpoint {
1320 public:
1321 PMemoryAllocationBreakpoint(DWORD point)
1322 {
1323 PMemoryHeap::SetAllocationBreakpoint(point);
1324 }
1325 };
1326
1327 #define PMEMORY_ALLOCATION_BREAKPOINT(point) PMemoryAllocationBreakpoint PMemoryAllocationBreakpointInstance(point)
1328
1329
1330 #else // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
1331
1332 #define PMEMORY_HEAP 0
1333
1334 #define PNEW new
1335
1336 #define PNEW_AND_DELETE_FUNCTIONS
1337
1338 #define runtime_malloc(s) malloc(s)
1339 #define runtime_free(p) free(p)
1340
1341 #define PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE
1342 #define PMEMORY_ALLOCATION_BREAKPOINT(point)
1343
1344 #endif // PMEMORY_CHECK || (defined(_MSC_VER) && defined(_DEBUG))
1345
1346
1348
1360 template <class Type, typename GuardType = unsigned>
1361 class PSingleton
1362 {
1363 protected:
1364 Type * m_instance;
1365 public:
1366 PSingleton()
1367 {
1368 static Type * s_pointer;
1369 static GuardType s_guard;
1370 if (s_guard++ != 0)
1371 s_guard = 1;
1372 else {
1373 #if PMEMORY_HEAP
1374 // Do this to make sure debugging is initialised as early as possible
1375 PMemoryHeap::Validate(NULL, NULL, NULL);
1376 #endif
1377 static Type s_instance;
1378 s_pointer = &s_instance;
1379 }
1380 m_instance = s_pointer;
1381 }
1382
1383 Type * operator->() const { return m_instance; }
1384 Type & operator* () const { return *m_instance; }
1385 };
1386
1387
1389 // Memory pool allocators
1390
1391 #if P_GNU_ALLOCATOR
1392
1393 #include <ext/mt_allocator.h>
1394
1395 /* Need this tempalte class specialisation of standard class to do the
1396 de-allocation of the pool memory. As per:
1397 http://gcc.gnu.org/viewcvs/trunk/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-6.cc?view=markup
1398 */
1399 template <bool _Thread>
1400 struct PMemoryPool : public __gnu_cxx::__pool<_Thread>
1401 {
1402 PMemoryPool()
1403 : __gnu_cxx::__pool<_Thread>()
1404 {
1405 }
1406
1407 PMemoryPool(const __gnu_cxx::__pool_base::_Tune& t)
1408 : __gnu_cxx::__pool<_Thread>(t)
1409 {
1410 }
1411 };
1412
1413 /*Do this template class specialisation so each type has it's own separate
1414 memory block for the pool. */
1415 template <class Type>
1416 struct PCommonPool : public __gnu_cxx::__common_pool_policy<PMemoryPool, true>
1417 {
1418 };
1419
1420 /*This template class specialisation adds the singleton instance.
1421 */
1422 template <class Type, class Pool = PCommonPool<Type> >
1423 struct PVariablePoolAllocator : public PSingleton<__gnu_cxx::__mt_alloc<Type, Pool> >
1424 {
1425 };
1426
1427 #if P_GNU_ALLOCATOR==1
1428 template <class Type>
1429 struct PFixedPoolAllocator : public PSingleton<__gnu_cxx::__mt_alloc<Type, PCommonPool<Type> > >
1430 {
1431 };
1432 #else
1433 #include <ext/bitmap_allocator.h>
1434 template <class Type>
1435 struct PFixedPoolAllocator : public PSingleton<__gnu_cxx::bitmap_allocator<Type> >
1436 {
1437 };
1438 #endif
1439
1440 #else
1441
1442 template <class Type, class Pool = void>
1443 struct PVariablePoolAllocator : public PSingleton<std::allocator<Type> >
1444 {
1445 };
1446
1447 template <class Type>
1448 struct PFixedPoolAllocator : public PSingleton<std::allocator<Type> >
1449 {
1450 };
1451
1452 #endif
1453
1454 #define PDECLARE_POOL_ALLOCATOR() \
1455 void * operator new(size_t nSize); \
1456 void * operator new(size_t nSize, const char * file, int line); \
1457 void operator delete(void * ptr); \
1458 void operator delete(void * ptr, const char *, int)
1459
1460 #define PDEFINE_POOL_ALLOCATOR(cls) \
1461 void * cls::operator new(size_t) { return PFixedPoolAllocator<cls>()->allocate(1); } \
1462 void * cls::operator new(size_t, const char *, int) { return PFixedPoolAllocator<cls>()->allocate(1); } \
1463 void cls::operator delete(void * ptr) { PFixedPoolAllocator<cls>()->deallocate((cls *)ptr, 1); } \
1464 void cls::operator delete(void * ptr, const char *, int) { PFixedPoolAllocator<cls>()->deallocate((cls *)ptr, 1); }
1465
1466
1467
1478 #define PCLASSINFO(cls, par) \
1479 public: \
1480 typedef cls P_thisClass; \
1481 static inline const char * Class() \
1482 { return #cls; } \
1483 virtual PBoolean InternalIsDescendant(const char * clsName) const \
1484 { return strcmp(clsName, this->Class()) == 0 || par::InternalIsDescendant(clsName); } \
1485 virtual const char * GetClass(unsigned ancestor = 0) const \
1486 { return ancestor > 0 ? par::GetClass(ancestor-1) : this->Class(); } \
1487 virtual PObject::Comparison CompareObjectMemoryDirect(const PObject & obj) const \
1488 { return PObject::InternalCompareObjectMemoryDirect(this, dynamic_cast<const cls *>(&obj), sizeof(cls)); } \
1489 PNEW_AND_DELETE_FUNCTIONS
1490
1492 #define PCLASSINFO_WITH_CLONE(cls, par) \
1493 PCLASSINFO(cls, par) \
1494 virtual PObject * Clone() const { return new cls(*this); }
1495
1496
1497 #define PIsDescendant(ptr, cls) (dynamic_cast<const cls *>(ptr) != NULL)
1498 #define PIsDescendantStr(ptr, str) ((ptr)->InternalIsDescendant(str))
1499
1500 #define PRemoveConst(cls, ptr) (const_cast<cls*>(ptr))
1501
1502 #if P_USE_ASSERTS
1503 template<class BaseClass> inline BaseClass * PAssertCast(BaseClass * obj, const char * file, int line)
1504 { if (obj == NULL) PAssertFunc(file, line, obj->Class(), PInvalidCast); return obj; }
1505 #define PDownCast(cls, ptr) PAssertCast<cls>(dynamic_cast<cls*>(ptr),__FILE__,__LINE__)
1506 #else
1507 #define PDownCast(cls, ptr) (dynamic_cast<cls*>(ptr))
1508 #endif
1509
1510
1519 #define PDECLARE_CLASS(cls, par) class cls : public par { PCLASSINFO(cls, par)
1520 #ifdef DOC_PLUS_PLUS
1521 } Match previous opening brace in doc++
1522 #endif
1523
1525 // The root of all evil ... umm classes
1526
1531 class PObject {
1532 protected:
1533 unsigned m_traceContextIdentifier;
1534 #if PTRACING==2
1535 public:
1538 unsigned GetTraceContextIdentifier() const { return m_traceContextIdentifier; }
1539 void SetTraceContextIdentifier(unsigned id) { m_traceContextIdentifier = id; }
1540 void GetTraceContextIdentifier(PObject & obj) { obj.m_traceContextIdentifier = m_traceContextIdentifier; }
1541 void GetTraceContextIdentifier(PObject * obj) { if (obj != NULL) obj->m_traceContextIdentifier = m_traceContextIdentifier; }
1542 void SetTraceContextIdentifier(const PObject & obj) { m_traceContextIdentifier = obj.m_traceContextIdentifier; }
1543 void SetTraceContextIdentifier(const PObject * obj) { if (obj != NULL) m_traceContextIdentifier = obj->m_traceContextIdentifier; }
1544 #endif // PTRACING==2
1545
1546 protected:
1550 PObject()
1551 : m_traceContextIdentifier(0)
1552 { }
1553
1554 public:
1555 /* Destructor required to get the "virtual". A PObject really has nothing
1556 to destroy.
1557 */
1558 virtual ~PObject() { }
1559
1572 static inline const char * Class() { return "PObject"; }
1573
1586 virtual const char * GetClass(unsigned ancestor = 0) const { return ancestor > 0 ? "" : this->Class(); }
1587
1588 PBoolean IsClass(const char * cls) const
1589 { return strcmp(cls, GetClass()) == 0; }
1590
1600 virtual PBoolean InternalIsDescendant(
1601 const char * clsName // Ancestor class name to compare against.
1602 ) const
1603 { return IsClass(clsName); }
1604
1605 __inline const PObject * PTraceObjectInstance() const { return this; }
1606 __inline static const PObject * PTraceObjectInstance(const char *) { return NULL; }
1607 __inline static const PObject * PTraceObjectInstance(const PObject * obj) { return obj; }
1609
1615 enum Comparison {
1616 LessThan = -1,
1617 EqualTo = 0,
1618 GreaterThan = 1
1619 };
1620
1632 virtual Comparison Compare(
1633 const PObject & obj // Object to compare against.
1634 ) const;
1635
1647 virtual Comparison CompareObjectMemoryDirect(
1648 const PObject & obj // Object to compare against.
1649 ) const;
1650
1652 static Comparison InternalCompareObjectMemoryDirect(
1653 const PObject * obj1,
1654 const PObject * obj2,
1655 PINDEX size
1656 );
1657
1663 bool operator==(
1664 const PObject & obj // Object to compare against.
1665 ) const { return Compare(obj) == EqualTo; }
1666
1672 bool operator!=(
1673 const PObject & obj // Object to compare against.
1674 ) const { return Compare(obj) != EqualTo; }
1675
1681 bool operator<(
1682 const PObject & obj // Object to compare against.
1683 ) const { return Compare(obj) == LessThan; }
1684
1690 bool operator>(
1691 const PObject & obj // Object to compare against.
1692 ) const { return Compare(obj) == GreaterThan; }
1693
1699 bool operator<=(
1700 const PObject & obj // Object to compare against.
1701 ) const { return Compare(obj) != GreaterThan; }
1702
1708 bool operator>=(
1709 const PObject & obj // Object to compare against.
1710 ) const { return Compare(obj) != LessThan; }
1712
1721 virtual void PrintOn(
1722 ostream &strm // Stream to print the object into.
1723 ) const;
1724
1731 virtual void ReadFrom(
1732 istream &strm // Stream to read the objects contents from.
1733 );
1734
1735
1741 inline friend ostream & operator<<(
1742 ostream &strm,
1743 const PObject & obj
1744 ) { obj.PrintOn(strm); return strm; }
1745
1751 inline friend istream & operator>>(
1752 istream &strm,
1753 PObject & obj
1754 ) { obj.ReadFrom(strm); return strm; }
1755
1756
1771 virtual PObject * Clone() const;
1772
1775 template <class CLS>
1776 CLS * CloneAs() const
1777 {
1778 PObject * clone = Clone();
1779 CLS * obj = dynamic_cast<CLS *>(clone);
1780 if (obj != NULL)
1781 return obj;
1782 delete clone;
1783 return NULL;
1784 }
1785
1797 virtual PINDEX HashFunction() const;
1799 };
1800
1802 // Platform independent types
1803
1804 // All these classes encapsulate primitive types such that they may be
1805 // transfered in a platform independent manner. In particular it is used to
1806 // do byte swapping for little endien and big endien processor architectures
1807 // as well as accommodating structure packing rules for memory structures.
1808
1809 #define PANSI_CHAR 1
1810 #define PLITTLE_ENDIAN 2
1811 #define PBIG_ENDIAN 3
1812
1813
1814 template <typename type>
1815 struct PIntSameOrder {
1816 __inline PIntSameOrder() : data(0) { }
1817 __inline PIntSameOrder(type value) : data(value) { }
1818 __inline PIntSameOrder(const PIntSameOrder & value) : data(value.data) { }
1819 __inline PIntSameOrder & operator=(type value) { data = value; return *this; }
1820 __inline PIntSameOrder & operator=(const PIntSameOrder & value) { data = value.data; return *this; }
1821 __inline operator type() const { return data; }
1822 __inline friend ostream & operator<<(ostream & s, const PIntSameOrder & v) { return s << v.data; }
1823 __inline friend istream & operator>>(istream & s, PIntSameOrder & v) { return s >> v.data; }
1824
1825 private:
1826 type data;
1827 };
1828
1829
1830 template <typename type>
1831 struct PIntReversedOrder {
1832 __inline PIntReversedOrder() : data(0) { }
1833 __inline PIntReversedOrder(type value) { ReverseBytes(value, data); }
1834 __inline PIntReversedOrder(const PIntReversedOrder & value) : data(value.data) { }
1835 __inline PIntReversedOrder & operator=(type value) { ReverseBytes(value, data); return *this; }
1836 __inline PIntReversedOrder & operator=(const PIntReversedOrder & value) { data = value.data; return *this; }
1837 __inline operator type() const { type value; ReverseBytes(data, value); return value; }
1838 __inline friend ostream & operator<<(ostream & s, const PIntReversedOrder & value) { return s << (type)value; }
1839 __inline friend istream & operator>>(istream & s, PIntReversedOrder & v) { type val; s >> val; v = val; return s; }
1840
1841 private:
1842 type data;
1843
1844 static __inline void ReverseBytes(const type & src, type & dst)
1845 {
1846 size_t s = sizeof(type)-1;
1847 for (size_t d = 0; d < sizeof(type); ++d,--s)
1848 ((BYTE *)&dst)[d] = ((const BYTE *)&src)[s];
1849 }
1850 };
1851
1852 #ifndef PCHAR8
1853 #define PCHAR8 PANSI_CHAR
1854 #endif
1855
1856 #if PCHAR8==PANSI_CHAR
1857 typedef PIntSameOrder<char> PChar8;
1858 #endif
1859
1860 typedef PIntSameOrder<char> PInt8;
1861
1862 typedef PIntSameOrder<unsigned char> PUInt8;
1863
1864 #if PBYTE_ORDER==PLITTLE_ENDIAN
1865 typedef PIntSameOrder<PInt16> PInt16l;
1866 #elif PBYTE_ORDER==PBIG_ENDIAN
1867 typedef PIntReversedOrder<PInt16> PInt16l;
1868 #endif
1869
1870 #if PBYTE_ORDER==PLITTLE_ENDIAN
1871 typedef PIntReversedOrder<PInt16> PInt16b;
1872 #elif PBYTE_ORDER==PBIG_ENDIAN
1873 typedef PIntSameOrder<PInt16> PInt16b;
1874 #endif
1875
1876 #if PBYTE_ORDER==PLITTLE_ENDIAN
1877 typedef PIntSameOrder<WORD> PUInt16l;
1878 #elif PBYTE_ORDER==PBIG_ENDIAN
1879 typedef PIntReversedOrder<WORD> PUInt16l;
1880 #endif
1881
1882 #if PBYTE_ORDER==PLITTLE_ENDIAN
1883 typedef PIntReversedOrder<WORD> PUInt16b;
1884 #elif PBYTE_ORDER==PBIG_ENDIAN
1885 typedef PIntSameOrder<WORD> PUInt16b;
1886 #endif
1887
1888 #if PBYTE_ORDER==PLITTLE_ENDIAN
1889 typedef PIntSameOrder<PInt32> PInt32l;
1890 #elif PBYTE_ORDER==PBIG_ENDIAN
1891 typedef PIntReversedOrder<PInt32> PInt32l;
1892 #endif
1893
1894 #if PBYTE_ORDER==PLITTLE_ENDIAN
1895 typedef PIntReversedOrder<PInt32> PInt32b;
1896 #elif PBYTE_ORDER==PBIG_ENDIAN
1897 typedef PIntSameOrder<PInt32> PInt32b;
1898 #endif
1899
1900 #if PBYTE_ORDER==PLITTLE_ENDIAN
1901 typedef PIntSameOrder<DWORD> PUInt32l;
1902 #elif PBYTE_ORDER==PBIG_ENDIAN
1903 typedef PIntReversedOrder<DWORD> PUInt32l;
1904 #endif
1905
1906 #if PBYTE_ORDER==PLITTLE_ENDIAN
1907 typedef PIntReversedOrder<DWORD> PUInt32b;
1908 #elif PBYTE_ORDER==PBIG_ENDIAN
1909 typedef PIntSameOrder<DWORD> PUInt32b;
1910 #endif
1911
1912 #if PBYTE_ORDER==PLITTLE_ENDIAN
1913 typedef PIntSameOrder<PInt64> PInt64l;
1914 #elif PBYTE_ORDER==PBIG_ENDIAN
1915 typedef PIntReversedOrder<PInt64> PInt64l;
1916 #endif
1917
1918 #if PBYTE_ORDER==PLITTLE_ENDIAN
1919 typedef PIntReversedOrder<PInt64> PInt64b;
1920 #elif PBYTE_ORDER==PBIG_ENDIAN
1921 typedef PIntSameOrder<PInt64> PInt64b;
1922 #endif
1923
1924 #if PBYTE_ORDER==PLITTLE_ENDIAN
1925 typedef PIntSameOrder<PUInt64> PUInt64l;
1926 #elif PBYTE_ORDER==PBIG_ENDIAN
1927 typedef PIntReversedOrder<PUInt64> PUInt64l;
1928 #endif
1929
1930 #if PBYTE_ORDER==PLITTLE_ENDIAN
1931 typedef PIntReversedOrder<PUInt64> PUInt64b;
1932 #elif PBYTE_ORDER==PBIG_ENDIAN
1933 typedef PIntSameOrder<PUInt64> PUInt64b;
1934 #endif
1935
1936 #if PBYTE_ORDER==PLITTLE_ENDIAN
1937 typedef PIntSameOrder<float> PFloat32l;
1938 #elif PBYTE_ORDER==PBIG_ENDIAN
1939 typedef PIntReversedOrder<float> PFloat32l;
1940 #endif
1941
1942 #if PBYTE_ORDER==PLITTLE_ENDIAN
1943 typedef PIntReversedOrder<float> PFloat32b;
1944 #elif PBYTE_ORDER==PBIG_ENDIAN
1945 typedef PIntSameOrder<float> PFloat32b;
1946 #endif
1947
1948 #if PBYTE_ORDER==PLITTLE_ENDIAN
1949 typedef PIntSameOrder<double> PFloat64l;
1950 #elif PBYTE_ORDER==PBIG_ENDIAN
1951 typedef PIntReversedOrder<double> PFloat64l;
1952 #endif
1953
1954 #if PBYTE_ORDER==PLITTLE_ENDIAN
1955 typedef PIntReversedOrder<double> PFloat64b;
1956 #elif PBYTE_ORDER==PBIG_ENDIAN
1957 typedef PIntSameOrder<double> PFloat64b;
1958 #endif
1959
1960 #ifndef NO_LONG_DOUBLE // stupid OSX compiler
1961 #if PBYTE_ORDER==PLITTLE_ENDIAN
1962 typedef PIntSameOrder<long double> PFloat80l;
1963 #elif PBYTE_ORDER==PBIG_ENDIAN
1964 typedef PIntReversedOrder<long double> PFloat80l;
1965 #endif
1966
1967 #if PBYTE_ORDER==PLITTLE_ENDIAN
1968 typedef PIntReversedOrder<long double> PFloat80b;
1969 #elif PBYTE_ORDER==PBIG_ENDIAN
1970 typedef PIntSameOrder<long double> PFloat80b;
1971 #endif
1972 #endif
1973
1974 typedef intptr_t P_INT_PTR;
1975
1976 #if defined(_MSC_VER)
1977 #define P_ALIGN_FIELD(f,a) __declspec(align(a)) f
1978 #define P_PACK_FIELD(f) __declspec(align(1)) f
1979 #elif defined(__GNUC__)
1980 #define P_ALIGN_FIELD(f,a) f __attribute__ ((aligned(a)))
1981 #define P_PACK_FIELD(f) f __attribute__ ((packed))
1982 #endif
1983
1984 typedef intptr_t P_INT_PTR;
1985
1987 // Miscellaneous
1988
1989 /*$MACRO PARRAYSIZE(array)
1990 This macro is used to calculate the number of array elements in a static
1991 array.
1992 */
1993 #define PARRAYSIZE(array) ((PINDEX)(sizeof(array)/sizeof(array[0])))
1994
1995 /*$MACRO PMIN(v1, v2)
1996 This macro is used to calculate the minimum of two values.
1997 Maps to std::min and is for backward compatibility only.
1998 */
1999 #define PMIN(v1, v2) std::min(v1, v2)
2000
2001 /*$MACRO PMAX(v1, v2)
2002 This macro is used to calculate the maximum of two values.
2003 Maps to std::max and is for backward compatibility only.
2004 */
2005 #define PMAX(v1, v2) std::max(v1, v2)
2006
2007 /*$MACRO PABS(val)
2008 This macro is used to calculate an absolute value.
2009 Maps to std::abs and is for backward compatibility only.
2010 */
2011 #define PABS(v) std::abs(v)
2012
2013
2014 #if _MSC_VER >= 1700
2015 class p_iostream : public std::iostream {
2016 public:
2017 p_iostream(std::streambuf * sbuf) : std::iostream(sbuf) { }
2018 private:
2019 virtual void __CLR_OR_THIS_CALL _Add_vtordisp1() { } // compiler bug workaround
2020 virtual void __CLR_OR_THIS_CALL _Add_vtordisp2() { } // compiler bug workaround
2021 };
2022 #define P_IOSTREAM p_iostream
2023 #else
2024 #define P_IOSTREAM std::iostream
2025 #endif
2026
2027
2028 #endif // PTLIB_OBJECT_H
2029
2030
2031 // End Of File ///////////////////////////////////////////////////////////////