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>
38 // An abstract allocator superclass, based on the simple malloc/realloc/free paradigm
39 // that CDSA loves so much. If you have an allocation strategy and want objects
40 // to be allocated through it, inherit from this.
44 virtual ~CssmAllocator();
45 virtual void *malloc(size_t) = 0;
46 virtual void free(void *) = 0;
47 virtual void *realloc(void *, size_t) = 0;
50 // Template versions for added expressiveness.
51 // Note that the integers are element counts, not byte sizes.
53 template <class T
> T
*alloc()
54 { return reinterpret_cast<T
*>(malloc(sizeof(T
))); }
56 template <class T
> T
*alloc(uint32 count
)
57 { return reinterpret_cast<T
*>(malloc(sizeof(T
) * count
)); }
59 template <class T
> T
*alloc(T
*old
, uint32 count
)
60 { return reinterpret_cast<T
*>(realloc(old
, sizeof(T
) * count
)); }
62 template <class Data
> CssmData
alloc(const Data
&source
)
64 size_t length
= source
.length();
65 return CssmData(memcpy(malloc(length
), source
.data(), length
), length
);
69 // Happier malloc/realloc for any type. Note that these still have
70 // the original (byte-sized) argument profile.
72 template <class T
> T
*malloc(size_t size
)
73 { return reinterpret_cast<T
*>(malloc(size
)); }
75 template <class T
> T
*realloc(void *addr
, size_t size
)
76 { return reinterpret_cast<T
*>(realloc(addr
, size
)); }
78 // All right, if you *really* have to have calloc...
79 void *calloc(size_t size
, unsigned int count
)
81 void *addr
= malloc(size
* count
);
82 memset(addr
, 0, size
* count
);
86 // compare CssmAllocators for identity
87 virtual bool operator == (const CssmAllocator
&alloc
) const;
90 // allocator chooser options
96 static CssmAllocator
&standard(uint32 request
= normal
);
101 // A POD wrapper for the memory functions structure passed around in CSSM.
103 class CssmMemoryFunctions
: public PodWrapper
<CssmMemoryFunctions
, CSSM_MEMORY_FUNCS
> {
105 CssmMemoryFunctions(const CSSM_MEMORY_FUNCS
&funcs
)
106 { *(CSSM_MEMORY_FUNCS
*)this = funcs
; }
107 CssmMemoryFunctions() { }
109 void *malloc(size_t size
) const;
110 void free(void *mem
) const { free_func(mem
, AllocRef
); }
111 void *realloc(void *mem
, size_t size
) const;
112 void *calloc(uint32 count
, size_t size
) const;
114 bool operator == (const CSSM_MEMORY_FUNCS
&other
) const
115 { return !memcmp(this, &other
, sizeof(*this)); }
118 inline void *CssmMemoryFunctions::malloc(size_t size
) const
120 if (void *addr
= malloc_func(size
, AllocRef
))
122 throw std::bad_alloc();
125 inline void *CssmMemoryFunctions::calloc(uint32 count
, size_t size
) const
127 if (void *addr
= calloc_func(count
, size
, AllocRef
))
129 throw std::bad_alloc();
132 inline void *CssmMemoryFunctions::realloc(void *mem
, size_t size
) const
134 if (void *addr
= realloc_func(mem
, size
, AllocRef
))
136 throw std::bad_alloc();
141 // A CssmAllocator based on CssmMemoryFunctions
143 class CssmMemoryFunctionsAllocator
: public CssmAllocator
{
145 CssmMemoryFunctionsAllocator(const CssmMemoryFunctions
&memFuncs
) : functions(memFuncs
) { }
147 void *malloc(size_t size
);
148 void free(void *addr
);
149 void *realloc(void *addr
, size_t size
);
151 operator const CssmMemoryFunctions
& () const { return functions
; }
154 const CssmMemoryFunctions functions
;
157 } // end namespace Security
160 // Global C++ allocation hooks to use CssmAllocators
162 inline void *operator new (size_t size
, CssmAllocator
&allocator
)
163 { return allocator
.malloc(size
); }
166 // You'd think that this is operator delete(const T *, CssmAllocator &), but you'd
167 // be wrong. Specialized operator delete is only called during constructor cleanup.
168 // Use this to cleanly destroy things.
171 inline void destroy(T
*obj
, CssmAllocator
&alloc
)
177 // untyped (release memory only, no destructor call)
178 inline void destroy(void *obj
, CssmAllocator
&alloc
)
187 // A MemoryFunctions object based on a CssmAllocator.
188 // Note that we don't copy the CssmAllocator object. It needs to live (at least)
189 // as long as any CssmAllocatorMemoryFunctions object based on it.
191 class CssmAllocatorMemoryFunctions
: public CssmMemoryFunctions
{
193 CssmAllocatorMemoryFunctions(CssmAllocator
&alloc
);
194 CssmAllocatorMemoryFunctions() { /*IFDEBUG(*/ AllocRef
= NULL
/*)*/ ; } // later assignment req'd
197 static void *relayMalloc(size_t size
, void *ref
);
198 static void relayFree(void *mem
, void *ref
);
199 static void *relayRealloc(void *mem
, size_t size
, void *ref
);
200 static void *relayCalloc(uint32 count
, size_t size
, void *ref
);
202 static CssmAllocator
&allocator(void *ref
)
203 { return *reinterpret_cast<CssmAllocator
*>(ref
); }
208 // A mixin class to automatically manage your allocator.
209 // To allow allocation (of your object) from any instance of CssmAllocator,
210 // inherit from CssmHeap. Your users can then create heap instances of your thing by
211 // new (an-allocator) YourClass(...)
213 // new YourClass(...)
214 // for the default allocation source. The beauty is that when someone does a
215 // delete pointer-to-your-instance
216 // then the magic fairies will find the allocator that created the object and ask it
217 // to free the memory (by calling its free() method).
218 // The price of all that glory is memory overhead - typically one pointer per object.
222 void *operator new (size_t size
, CssmAllocator
*alloc
= NULL
);
223 void operator delete (void *addr
, size_t size
);
224 void operator delete (void *addr
, size_t size
, CssmAllocator
*alloc
);
229 // Here is a version of auto_ptr that works with CssmAllocators. It is designed
230 // to be pretty much a drop-in replacement. It requires an allocator as a constructor
231 // argument, of course.
232 // Note that CssmAutoPtr<void> is perfectly valid, unlike its auto_ptr look-alike.
233 // You can't dereference it, naturally.
238 CssmAllocator
&allocator
;
240 CssmAutoPtr(CssmAllocator
&alloc
= CssmAllocator::standard())
241 : allocator(alloc
), mine(NULL
) { }
242 CssmAutoPtr(CssmAllocator
&alloc
, T
*p
)
243 : allocator(alloc
), mine(p
) { }
245 : allocator(CssmAllocator::standard()), mine(p
) { }
246 template <class T1
> CssmAutoPtr(CssmAutoPtr
<T1
> &src
)
247 : allocator(src
.allocator
), mine(src
.release()) { }
248 template <class T1
> CssmAutoPtr(CssmAllocator
&alloc
, CssmAutoPtr
<T1
> &src
)
249 : allocator(alloc
), mine(rc
.release()) { assert(allocator
== src
.allocator
); }
251 ~CssmAutoPtr() { destroy(mine
); }
253 T
*get() const throw() { return mine
; }
254 T
*release() { T
*result
= mine
; mine
= NULL
; return result
; }
255 void reset() { allocator
.free(mine
); mine
= NULL
; }
257 operator T
* () const { return mine
; }
258 T
*operator -> () const { return mine
; }
259 T
&operator * () const { assert(mine
); return *mine
; }
265 // specialization for void (i.e. void *), omitting the troublesome dereferencing ops.
267 class CssmAutoPtr
<void> {
269 CssmAllocator
&allocator
;
271 CssmAutoPtr(CssmAllocator
&alloc
) : allocator(alloc
), mine(NULL
) { }
272 CssmAutoPtr(CssmAllocator
&alloc
, void *p
) : allocator(alloc
), mine(p
) { }
273 template <class T1
> CssmAutoPtr(CssmAutoPtr
<T1
> &src
)
274 : allocator(src
.allocator
), mine(src
.release()) { }
275 template <class T1
> CssmAutoPtr(CssmAllocator
&alloc
, CssmAutoPtr
<T1
> &src
)
276 : allocator(alloc
), mine(rc
.release()) { assert(allocator
== src
.allocator
); }
278 ~CssmAutoPtr() { destroy(mine
, allocator
); }
280 void *get() throw() { return mine
; }
281 void *release() { void *result
= mine
; mine
= NULL
; return result
; }
282 void reset() { allocator
.free(mine
); mine
= NULL
; }
290 // Convenience forms of CssmAutoPtr that automatically make their (initial) object.
293 class CssmNewAutoPtr
: public CssmAutoPtr
<T
> {
295 CssmNewAutoPtr(CssmAllocator
&alloc
= CssmAllocator::standard())
296 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T
) { }
299 CssmNewAutoPtr(CssmAllocator
&alloc
, A1
&arg1
) : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
)) { }
301 CssmNewAutoPtr(CssmAllocator
&alloc
, const A1
&arg1
)
302 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
)) { }
304 template <class A1
, class A2
>
305 CssmNewAutoPtr(CssmAllocator
&alloc
, A1
&arg1
, A2
&arg2
)
306 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
307 template <class A1
, class A2
>
308 CssmNewAutoPtr(CssmAllocator
&alloc
, const A1
&arg1
, A2
&arg2
)
309 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
310 template <class A1
, class A2
>
311 CssmNewAutoPtr(CssmAllocator
&alloc
, A1
&arg1
, const A2
&arg2
)
312 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
313 template <class A1
, class A2
>
314 CssmNewAutoPtr(CssmAllocator
&alloc
, const A1
&arg1
, const A2
&arg2
)
315 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
320 // A CssmAllocator that keeps track of allocations and can throw everything
321 // away unless explicitly committed.
323 class TrackingAllocator
: public CssmAllocator
326 TrackingAllocator(CssmAllocator
&inAllocator
) : mAllocator(inAllocator
) {}
327 virtual ~TrackingAllocator();
329 void *malloc(size_t inSize
)
331 void *anAddress
= mAllocator
.malloc(inSize
);
332 mAllocSet
.insert(anAddress
);
336 void free(void *inAddress
)
338 mAllocator
.free(inAddress
);
339 mAllocSet
.erase(inAddress
);
342 void *realloc(void *inAddress
, size_t inNewSize
)
344 void *anAddress
= mAllocator
.realloc(inAddress
, inNewSize
);
345 if (anAddress
!= inAddress
)
347 mAllocSet
.erase(inAddress
);
348 mAllocSet
.insert(anAddress
);
354 void commit() { mAllocSet
.clear(); }
356 typedef std::set
<void *> AllocSet
;
358 CssmAllocator
&mAllocator
;
362 } // end namespace Security
364 #ifdef _CPP_CSSMALLOC
368 #endif //_H_CSSMALLOC