1 |
/** |
2 |
* memory.h: Memory templates. |
3 |
* |
4 |
* Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team |
5 |
* Rights to this code are documented in doc/pod/gplicense.pod. |
6 |
* |
7 |
* $Id: memory.h,v 1.5 2007-09-16 18:54:42 pippijn Exp $ |
8 |
*/ |
9 |
|
10 |
#ifndef ERMYTH_MEMORY_H |
11 |
#define ERMYTH_MEMORY_H |
12 |
|
13 |
#include <vector> |
14 |
|
15 |
#include <ermyth/type_traits.h> |
16 |
|
17 |
namespace impl |
18 |
{ |
19 |
inline void * |
20 |
smalloc (size_t n) throw (std::bad_alloc) |
21 |
{ |
22 |
void *ptr = malloc (n); |
23 |
|
24 |
if (!ptr) |
25 |
throw std::bad_alloc (); |
26 |
|
27 |
return ptr; |
28 |
} |
29 |
|
30 |
inline void * |
31 |
smalloc (size_t n, void const * const src) throw (std::bad_alloc) |
32 |
{ |
33 |
void *ptr = smalloc (n); |
34 |
|
35 |
if (src) |
36 |
memcpy (ptr, src, n); |
37 |
else |
38 |
memset (ptr, 0, n); |
39 |
|
40 |
return ptr; |
41 |
} |
42 |
|
43 |
// safe and slow version of above: never tries to copy more than len from src |
44 |
inline void * |
45 |
smalloc (size_t n, void *src, size_t len) throw (std::bad_alloc) |
46 |
{ |
47 |
size_t max = n >= len ? n : len; |
48 |
void *ptr = smalloc (max); |
49 |
|
50 |
if (src) |
51 |
{ |
52 |
memcpy (ptr, src, len); |
53 |
memset (((char *)(ptr)) + len, 0, max - len); // XXX: hack to allow pointer arithmetic |
54 |
} |
55 |
else |
56 |
memset (ptr, 0, max); |
57 |
|
58 |
return ptr; |
59 |
} |
60 |
} |
61 |
|
62 |
template<typename T> |
63 |
inline T * |
64 |
salloc (size_t n = 1) throw (std::bad_alloc) |
65 |
{ |
66 |
return (T *) impl::smalloc (n * sizeof (T)); |
67 |
} |
68 |
|
69 |
template<typename T> |
70 |
inline T * |
71 |
salloc (size_t n, T const * const src) throw (std::bad_alloc) |
72 |
{ |
73 |
return (T *) impl::smalloc (n * sizeof (T), src); |
74 |
} |
75 |
|
76 |
// template counterpart of the safe copying allocator |
77 |
template<typename T> |
78 |
inline T * |
79 |
salloc (size_t n, T *src, size_t len) throw (std::bad_alloc) |
80 |
{ |
81 |
return (T *) impl::smalloc (n * sizeof (T), src, len); |
82 |
} |
83 |
|
84 |
template<typename T> |
85 |
inline T * |
86 |
salloc (size_t n, char c) throw (std::bad_alloc) |
87 |
{ |
88 |
T *ptr = (T *) impl::smalloc (n * sizeof (T)); |
89 |
return memset (ptr, c, n * sizeof (T)); |
90 |
} |
91 |
|
92 |
template<typename T> |
93 |
inline void |
94 |
sfree (T *ptr) throw () |
95 |
{ |
96 |
free (ptr); |
97 |
} |
98 |
|
99 |
template<typename T> |
100 |
inline void |
101 |
sfree (T *ptr, size_t n) throw () |
102 |
{ |
103 |
free (ptr); |
104 |
} |
105 |
|
106 |
// makes dynamically allocated objects zero-initialised |
107 |
struct zero_initialised |
108 |
{ |
109 |
void *operator new (size_t s) |
110 |
{ |
111 |
void *p = impl::smalloc (s); |
112 |
memset (p, 0, s); |
113 |
return p; |
114 |
} |
115 |
|
116 |
void *operator new[] (size_t s) |
117 |
{ |
118 |
void *p = impl::smalloc (s); |
119 |
memset (p, 0, s); |
120 |
return p; |
121 |
} |
122 |
|
123 |
void operator delete (void *p, size_t s) |
124 |
{ |
125 |
free (p); |
126 |
} |
127 |
|
128 |
void operator delete[] (void *p, size_t s) |
129 |
{ |
130 |
free (p); |
131 |
} |
132 |
}; |
133 |
|
134 |
E char *sstrdup (char const * const s); |
135 |
E char *sstrndup (char const * const s, size_t len); |
136 |
|
137 |
template<size_t N> |
138 |
inline char * |
139 |
sstrndup (char const (&s)[N]) |
140 |
{ |
141 |
return sstrndup (s, N); |
142 |
} |
143 |
|
144 |
struct garbage_collector |
145 |
{ |
146 |
void insert (void *p) |
147 |
{ |
148 |
mortals.push_back (p); |
149 |
} |
150 |
|
151 |
void collect () |
152 |
{ |
153 |
while (!mortals.empty ()) |
154 |
{ |
155 |
sfree (mortals.back ()); |
156 |
mortals.pop_back (); |
157 |
} |
158 |
} |
159 |
|
160 |
private: |
161 |
std::vector<void *> mortals; |
162 |
}; |
163 |
|
164 |
E garbage_collector gc; |
165 |
|
166 |
#endif |