2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // cssmalloc - memory allocation in the CDSA world
25 #include <Security/utilities.h>
26 #include <Security/cssm.h>
37 // An abstract allocator superclass, based on the simple malloc/realloc/free paradigm
38 // that CDSA loves so much. If you have an allocation strategy and want objects
39 // to be allocated through it, inherit from this.
43 virtual ~CssmAllocator();
44 virtual void *malloc(size_t) throw(std::bad_alloc
) = 0;
45 virtual void free(void *) throw() = 0;
46 virtual void *realloc(void *, size_t) throw(std::bad_alloc
) = 0;
49 // Template versions for added expressiveness.
50 // Note that the integers are element counts, not byte sizes.
52 template <class T
> T
*alloc() throw(std::bad_alloc
)
53 { return reinterpret_cast<T
*>(malloc(sizeof(T
))); }
55 template <class T
> T
*alloc(uint32 count
) throw(std::bad_alloc
)
56 { return reinterpret_cast<T
*>(malloc(sizeof(T
) * count
)); }
58 template <class T
> T
*alloc(T
*old
, uint32 count
) throw(std::bad_alloc
)
59 { return reinterpret_cast<T
*>(realloc(old
, sizeof(T
) * count
)); }
61 template <class Data
> CssmData
alloc(const Data
&source
) throw(std::bad_alloc
)
63 size_t length
= source
.length();
64 return CssmData(memcpy(malloc(length
), source
.data(), length
), length
);
68 // Happier malloc/realloc for any type. Note that these still have
69 // the original (byte-sized) argument profile.
71 template <class T
> T
*malloc(size_t size
) throw(std::bad_alloc
)
72 { return reinterpret_cast<T
*>(malloc(size
)); }
74 template <class T
> T
*realloc(void *addr
, size_t size
) throw(std::bad_alloc
)
75 { return reinterpret_cast<T
*>(realloc(addr
, size
)); }
77 // All right, if you *really* have to have calloc...
78 void *calloc(size_t size
, unsigned int count
) throw(std::bad_alloc
)
80 void *addr
= malloc(size
* count
);
81 memset(addr
, 0, size
* count
);
85 // compare CssmAllocators for identity
86 virtual bool operator == (const CssmAllocator
&alloc
) const throw();
89 // allocator chooser options
95 static CssmAllocator
&standard(uint32 request
= normal
);
100 // A POD wrapper for the memory functions structure passed around in CSSM.
102 class CssmMemoryFunctions
: public PodWrapper
<CssmMemoryFunctions
, CSSM_MEMORY_FUNCS
> {
104 CssmMemoryFunctions(const CSSM_MEMORY_FUNCS
&funcs
)
105 { *(CSSM_MEMORY_FUNCS
*)this = funcs
; }
106 CssmMemoryFunctions() { }
108 void *malloc(size_t size
) const throw(std::bad_alloc
);
109 void free(void *mem
) const throw() { free_func(mem
, AllocRef
); }
110 void *realloc(void *mem
, size_t size
) const throw(std::bad_alloc
);
111 void *calloc(uint32 count
, size_t size
) const throw(std::bad_alloc
);
113 bool operator == (const CSSM_MEMORY_FUNCS
&other
) const throw()
114 { return !memcmp(this, &other
, sizeof(*this)); }
117 inline void *CssmMemoryFunctions::malloc(size_t size
) const throw(std::bad_alloc
)
119 if (void *addr
= malloc_func(size
, AllocRef
))
121 throw std::bad_alloc();
124 inline void *CssmMemoryFunctions::calloc(uint32 count
, size_t size
) const throw(std::bad_alloc
)
126 if (void *addr
= calloc_func(count
, size
, AllocRef
))
128 throw std::bad_alloc();
131 inline void *CssmMemoryFunctions::realloc(void *mem
, size_t size
) const throw(std::bad_alloc
)
133 if (void *addr
= realloc_func(mem
, size
, AllocRef
))
135 throw std::bad_alloc();
140 // A CssmAllocator based on CssmMemoryFunctions
142 class CssmMemoryFunctionsAllocator
: public CssmAllocator
{
144 CssmMemoryFunctionsAllocator(const CssmMemoryFunctions
&memFuncs
) : functions(memFuncs
) { }
146 void *malloc(size_t size
) throw(std::bad_alloc
);
147 void free(void *addr
) throw();
148 void *realloc(void *addr
, size_t size
) throw(std::bad_alloc
);
150 operator const CssmMemoryFunctions
& () const throw() { return functions
; }
153 const CssmMemoryFunctions functions
;
156 } // end namespace Security
159 // Global C++ allocation hooks to use CssmAllocators
161 inline void *operator new (size_t size
, CssmAllocator
&allocator
) throw (std::bad_alloc
)
162 { return allocator
.malloc(size
); }
164 inline void *operator new[] (size_t size
, CssmAllocator
&allocator
) throw (std::bad_alloc
)
165 { return allocator
.malloc(size
); }
169 // You'd think that this is operator delete(const T *, CssmAllocator &), but you'd
170 // be wrong. Specialized operator delete is only called during constructor cleanup.
171 // Use this to cleanly destroy things.
174 inline void destroy(T
*obj
, CssmAllocator
&alloc
) throw()
180 // untyped (release memory only, no destructor call)
181 inline void destroy(void *obj
, CssmAllocator
&alloc
) throw()
190 // A MemoryFunctions object based on a CssmAllocator.
191 // Note that we don't copy the CssmAllocator object. It needs to live (at least)
192 // as long as any CssmAllocatorMemoryFunctions object based on it.
194 class CssmAllocatorMemoryFunctions
: public CssmMemoryFunctions
{
196 CssmAllocatorMemoryFunctions(CssmAllocator
&alloc
);
197 CssmAllocatorMemoryFunctions() { /*IFDEBUG(*/ AllocRef
= NULL
/*)*/ ; } // later assignment req'd
200 static void *relayMalloc(size_t size
, void *ref
) throw(std::bad_alloc
);
201 static void relayFree(void *mem
, void *ref
) throw();
202 static void *relayRealloc(void *mem
, size_t size
, void *ref
) throw(std::bad_alloc
);
203 static void *relayCalloc(uint32 count
, size_t size
, void *ref
) throw(std::bad_alloc
);
205 static CssmAllocator
&allocator(void *ref
) throw()
206 { return *reinterpret_cast<CssmAllocator
*>(ref
); }
211 // A mixin class to automagically manage your allocator.
212 // To allow allocation (of your object) from any instance of CssmAllocator,
213 // inherit from CssmHeap. Your users can then create heap instances of your thing by
214 // new (an-allocator) YourClass(...)
216 // new YourClass(...)
217 // for the default allocation source. The beauty is that when someone does a
218 // delete pointer-to-your-instance
219 // then the magic fairies will find the allocator that created the object and ask it
220 // to free the memory (by calling its free() method).
221 // The price of all that glory is memory overhead - typically one pointer per object.
225 void *operator new (size_t size
, CssmAllocator
*alloc
= NULL
) throw(std::bad_alloc
);
226 void operator delete (void *addr
, size_t size
) throw();
227 void operator delete (void *addr
, size_t size
, CssmAllocator
*alloc
) throw();
232 // Here is a version of auto_ptr that works with CssmAllocators. It is designed
233 // to be pretty much a drop-in replacement. It requires an allocator as a constructor
234 // argument, of course.
235 // Note that CssmAutoPtr<void> is perfectly valid, unlike its auto_ptr look-alike.
236 // You can't dereference it, naturally.
241 CssmAllocator
&allocator
;
243 CssmAutoPtr(CssmAllocator
&alloc
= CssmAllocator::standard())
244 : allocator(alloc
), mine(NULL
) { }
245 CssmAutoPtr(CssmAllocator
&alloc
, T
*p
)
246 : allocator(alloc
), mine(p
) { }
248 : allocator(CssmAllocator::standard()), mine(p
) { }
249 template <class T1
> CssmAutoPtr(CssmAutoPtr
<T1
> &src
)
250 : allocator(src
.allocator
), mine(src
.release()) { }
251 template <class T1
> CssmAutoPtr(CssmAllocator
&alloc
, CssmAutoPtr
<T1
> &src
)
252 : allocator(alloc
), mine(rc
.release()) { assert(allocator
== src
.allocator
); }
254 ~CssmAutoPtr() { allocator
.free(mine
); }
256 T
*get() const throw() { return mine
; }
257 T
*release() { T
*result
= mine
; mine
= NULL
; return result
; }
258 void reset() { allocator
.free(mine
); mine
= NULL
; }
260 operator T
* () const { return mine
; }
261 T
*operator -> () const { return mine
; }
262 T
&operator * () const { assert(mine
); return *mine
; }
268 // specialization for void (i.e. void *), omitting the troublesome dereferencing ops.
270 class CssmAutoPtr
<void> {
272 CssmAllocator
&allocator
;
274 CssmAutoPtr(CssmAllocator
&alloc
) : allocator(alloc
), mine(NULL
) { }
275 CssmAutoPtr(CssmAllocator
&alloc
, void *p
) : allocator(alloc
), mine(p
) { }
276 template <class T1
> CssmAutoPtr(CssmAutoPtr
<T1
> &src
)
277 : allocator(src
.allocator
), mine(src
.release()) { }
278 template <class T1
> CssmAutoPtr(CssmAllocator
&alloc
, CssmAutoPtr
<T1
> &src
)
279 : allocator(alloc
), mine(rc
.release()) { assert(allocator
== src
.allocator
); }
281 ~CssmAutoPtr() { destroy(mine
, allocator
); }
283 void *get() throw() { return mine
; }
284 void *release() { void *result
= mine
; mine
= NULL
; return result
; }
285 void reset() { allocator
.free(mine
); mine
= NULL
; }
293 // Convenience forms of CssmAutoPtr that automatically make their (initial) object.
296 class CssmNewAutoPtr
: public CssmAutoPtr
<T
> {
298 CssmNewAutoPtr(CssmAllocator
&alloc
= CssmAllocator::standard())
299 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T
) { }
302 CssmNewAutoPtr(CssmAllocator
&alloc
, A1
&arg1
) : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
)) { }
304 CssmNewAutoPtr(CssmAllocator
&alloc
, const A1
&arg1
)
305 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
)) { }
307 template <class A1
, class A2
>
308 CssmNewAutoPtr(CssmAllocator
&alloc
, A1
&arg1
, A2
&arg2
)
309 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
310 template <class A1
, class A2
>
311 CssmNewAutoPtr(CssmAllocator
&alloc
, const A1
&arg1
, A2
&arg2
)
312 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
313 template <class A1
, class A2
>
314 CssmNewAutoPtr(CssmAllocator
&alloc
, A1
&arg1
, const A2
&arg2
)
315 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
316 template <class A1
, class A2
>
317 CssmNewAutoPtr(CssmAllocator
&alloc
, const A1
&arg1
, const A2
&arg2
)
318 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
323 // A generic helper for the unhappily ubiquitous CSSM-style
324 // (count, pointer-to-array) style of arrays.
326 template <class Base
, class Wrapper
= Base
>
329 CssmVector(uint32
&cnt
, Base
* &vec
, CssmAllocator
&alloc
= CssmAllocator::standard())
330 : count(cnt
), vector(reinterpret_cast<Wrapper
* &>(vec
)),
337 ~CssmVector() { allocator
.free(vector
); }
341 CssmAllocator
&allocator
;
344 Wrapper
&operator [] (uint32 ix
)
345 { assert(ix
< count
); return vector
[ix
]; }
347 void operator += (const Wrapper
&add
)
349 vector
= reinterpret_cast<Wrapper
*>(allocator
.realloc(vector
, (count
+ 1) * sizeof(Wrapper
)));
350 //@@@???compiler bug??? vector = allocator.alloc<Wrapper>(vector, count + 1);
351 vector
[count
++] = add
;
356 } // end namespace Security
358 #ifdef _CPP_CSSMALLOC
362 #endif //_H_CSSMALLOC