Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | /* |
2 | * Portions of this file are copyright Rebirth contributors and licensed as |
||
3 | * described in COPYING.txt. |
||
4 | * Portions of this file are copyright Parallax Software and licensed |
||
5 | * according to the Parallax license below. |
||
6 | * See COPYING.txt for license details. |
||
7 | |||
8 | THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX |
||
9 | SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO |
||
10 | END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A |
||
11 | ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS |
||
12 | IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS |
||
13 | SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE |
||
14 | FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE |
||
15 | CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS |
||
16 | AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. |
||
17 | COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. |
||
18 | */ |
||
19 | |||
20 | #pragma once |
||
21 | |||
22 | #include <stdlib.h> |
||
23 | #include <type_traits> |
||
24 | |||
25 | #ifdef __cplusplus |
||
26 | #include <memory> |
||
27 | #include "dxxsconf.h" |
||
28 | #include "dsx-ns.h" |
||
29 | #include <utility> |
||
30 | |||
31 | #define MEM_K 1.5 // Dynamic array growth factor |
||
32 | |||
33 | #ifdef DEBUG_BIAS_MEMORY_ALLOCATIONS |
||
34 | #include <array> |
||
35 | #define DXX_DEBUG_BIAS_MEMORY_ALLOCATION (sizeof(std::array<double, 2>)) |
||
36 | #else |
||
37 | #define DXX_DEBUG_BIAS_MEMORY_ALLOCATION (0) |
||
38 | #endif |
||
39 | |||
40 | namespace dcx { |
||
41 | |||
42 | #ifdef DEBUG_MEMORY_ALLOCATIONS |
||
43 | void mem_init(void); |
||
44 | |||
45 | void mem_display_blocks(); |
||
46 | __attribute_alloc_size(1) |
||
47 | __attribute_malloc() |
||
48 | void *mem_malloc(size_t size, const char *var, const char *file, unsigned line); |
||
49 | void * mem_calloc( size_t nmemb, size_t size, const char * var, const char * filename, unsigned line) __attribute_alloc_size(1,2) __attribute_malloc(); |
||
50 | __attribute_alloc_size(2) |
||
51 | void *mem_realloc(void *buffer, size_t size, const char *var, const char *file, unsigned line); |
||
52 | extern void mem_free( void * buffer ); |
||
53 | |||
54 | /* DPH: Changed malloc, etc. to d_malloc. Overloading system calls is very evil and error prone */ |
||
55 | |||
56 | // Checks to see if any blocks are overwritten |
||
57 | void mem_validate_heap(); |
||
58 | |||
59 | #define mem_calloc(nmemb,size,var,file,line) ((mem_calloc)((size) ? (nmemb) : 0, (size), (var), (file), (line))) |
||
60 | |||
61 | #else |
||
62 | |||
63 | #ifdef DEBUG_BIAS_MEMORY_ALLOCATIONS |
||
64 | #define bias_malloc(SIZE) ({ \ |
||
65 | auto p = malloc((SIZE) + DXX_DEBUG_BIAS_MEMORY_ALLOCATION); \ |
||
66 | p ? p + DXX_DEBUG_BIAS_MEMORY_ALLOCATION : p; \ |
||
67 | }) |
||
68 | /* Bias calloc wastes a bit extra to keep the math simple */ |
||
69 | #define bias_calloc(NMEMB,SIZE) ({ \ |
||
70 | auto p = calloc((NMEMB), (SIZE) + DXX_DEBUG_BIAS_MEMORY_ALLOCATION); \ |
||
71 | p ? p + DXX_DEBUG_BIAS_MEMORY_ALLOCATION : p; \ |
||
72 | }) |
||
73 | #define bias_realloc(PTR,SIZE) ({ \ |
||
74 | auto p = realloc(reinterpret_cast<char *>(PTR) - DXX_DEBUG_BIAS_MEMORY_ALLOCATION, (SIZE) + DXX_DEBUG_BIAS_MEMORY_ALLOCATION); \ |
||
75 | p ? p + DXX_DEBUG_BIAS_MEMORY_ALLOCATION : p; \ |
||
76 | }) |
||
77 | #define bias_free(PTR) free(reinterpret_cast<char *>(PTR) - DXX_DEBUG_BIAS_MEMORY_ALLOCATION) |
||
78 | #else |
||
79 | #define bias_malloc malloc |
||
80 | #define bias_calloc calloc |
||
81 | #define bias_realloc realloc |
||
82 | #define bias_free free |
||
83 | #endif |
||
84 | |||
85 | #define mem_malloc(size,var,file,line) ((void)var,(void)file,(void)line,bias_malloc((size))) |
||
86 | #define mem_calloc(nmemb,size,var,file,line) ((void)var,(void)file,(void)line,bias_calloc((nmemb),(size))) |
||
87 | #define mem_realloc(ptr,size,var,file,line) ((void)var,(void)file,(void)line,bias_realloc((ptr),(size))) |
||
88 | #define mem_free bias_free |
||
89 | |||
90 | static inline void mem_init(void) |
||
91 | { |
||
92 | } |
||
93 | #endif |
||
94 | |||
95 | template <typename T> |
||
96 | T *MALLOC(T *&r, std::size_t count, const char *var, const char *file, unsigned line) |
||
97 | { |
||
98 | static_assert(std::is_pod<T>::value, "MALLOC cannot allocate non-POD"); |
||
99 | return r = reinterpret_cast<T *>(mem_malloc(count * sizeof(T), var, file, line)); |
||
100 | } |
||
101 | |||
102 | template <typename T> |
||
103 | T *CALLOC(T *&r, std::size_t count, const char *var, const char *file, unsigned line) |
||
104 | { |
||
105 | static_assert(std::is_pod<T>::value, "CALLOC cannot allocate non-POD"); |
||
106 | return r = reinterpret_cast<T *>(mem_calloc(count, sizeof(T), var, file, line)); |
||
107 | } |
||
108 | |||
109 | #define d_malloc(size) mem_malloc((size),"Unknown", __FILE__,__LINE__ ) |
||
110 | #define d_realloc(ptr,size) mem_realloc((ptr),(size),"Unknown", __FILE__,__LINE__ ) |
||
111 | template <typename T> |
||
112 | static inline void d_free(T *&ptr) |
||
113 | { |
||
114 | static_assert((std::is_same<T, void>::value || std::is_pod<T>::value), "d_free cannot free non-POD"); |
||
115 | mem_free(std::exchange(ptr, nullptr)); |
||
116 | } |
||
117 | |||
118 | template <typename T> |
||
119 | class RAIIdmem_deleter |
||
120 | { |
||
121 | public: |
||
122 | void operator()(T *v) const |
||
123 | { |
||
124 | d_free(v); |
||
125 | } |
||
126 | }; |
||
127 | |||
128 | template <typename T> |
||
129 | class RAIIdmem_deleter<T[]> : public RAIIdmem_deleter<T> |
||
130 | { |
||
131 | public: |
||
132 | typedef T *pointer; |
||
133 | }; |
||
134 | |||
135 | template <typename T> |
||
136 | class RAIIdmem : public std::unique_ptr<T, RAIIdmem_deleter<T>> |
||
137 | { |
||
138 | typedef std::unique_ptr<T, RAIIdmem_deleter<T>> base_ptr; |
||
139 | public: |
||
140 | static_assert(std::is_pod<typename base_ptr::element_type>::value, "RAIIdmem cannot manage non-POD"); |
||
141 | DXX_INHERIT_CONSTRUCTORS(RAIIdmem, base_ptr); |
||
142 | }; |
||
143 | |||
144 | /* Disallow C-style arrays of known bound. Use RAIIdmem<std::array<T, N>> |
||
145 | * for this case. |
||
146 | */ |
||
147 | template <typename T, std::size_t N> |
||
148 | class RAIIdmem<T[N]> |
||
149 | { |
||
150 | public: |
||
151 | RAIIdmem() = delete; |
||
152 | }; |
||
153 | |||
154 | template <typename T> |
||
155 | RAIIdmem<T> &MALLOC(RAIIdmem<T> &r, std::size_t count, const char *var, const char *file, unsigned line) |
||
156 | { |
||
157 | typename RAIIdmem<T>::pointer p; |
||
158 | return r.reset(MALLOC<typename RAIIdmem<T>::element_type>(p, count, var, file, line)), r; |
||
159 | } |
||
160 | |||
161 | template <typename T> |
||
162 | RAIIdmem<T[]> &MALLOC(RAIIdmem<T[]> &r, const std::size_t count, const char *const var, const char *const file, const unsigned line) |
||
163 | { |
||
164 | return MALLOC<T[]>(r, count, var, file, line); |
||
165 | } |
||
166 | |||
167 | template <typename T> |
||
168 | void CALLOC(RAIIdmem<T> &r, std::size_t count, const char *var, const char *file, unsigned line) |
||
169 | { |
||
170 | typename RAIIdmem<T>::pointer p; |
||
171 | r.reset(CALLOC<typename RAIIdmem<T>::element_type>(p, count, var, file, line)); |
||
172 | } |
||
173 | |||
174 | #define MALLOC( var, type, count ) (MALLOC<type>(var, (count),#var, __FILE__,__LINE__ )) |
||
175 | #define CALLOC( var, type, count ) (CALLOC<type>(var, (count),#var, __FILE__,__LINE__ )) |
||
176 | |||
177 | } |
||
178 | |||
179 | #endif |