]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/alloc.h
2 * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 // alloc - abstract malloc-like allocator abstraction
31 #include <security_utilities/utilities.h>
39 // An abstract allocator superclass, based on the simple malloc/realloc/free paradigm
40 // that CDSA loves so much. If you have an allocation strategy and want objects
41 // to be allocated through it, inherit from this.
46 virtual void *malloc(size_t) throw(std::bad_alloc
) = 0;
47 virtual void free(void *) throw() = 0;
48 virtual void *realloc(void *, size_t) throw(std::bad_alloc
) = 0;
51 // Template versions for added expressiveness.
52 // Note that the integers are element counts, not byte sizes.
54 template <class T
> T
*alloc() throw(std::bad_alloc
)
55 { return reinterpret_cast<T
*>(malloc(sizeof(T
))); }
57 template <class T
> T
*alloc(UInt32 count
) throw(std::bad_alloc
)
58 { return reinterpret_cast<T
*>(malloc(sizeof(T
) * count
)); }
60 template <class T
> T
*alloc(T
*old
, UInt32 count
) throw(std::bad_alloc
)
61 { return reinterpret_cast<T
*>(realloc(old
, sizeof(T
) * count
)); }
65 // Happier malloc/realloc for any type. Note that these still have
66 // the original (byte-sized) argument profile.
68 template <class T
> T
*malloc(size_t size
) throw(std::bad_alloc
)
69 { return reinterpret_cast<T
*>(malloc(size
)); }
71 template <class T
> T
*realloc(void *addr
, size_t size
) throw(std::bad_alloc
)
72 { return reinterpret_cast<T
*>(realloc(addr
, size
)); }
74 // All right, if you *really* have to have calloc...
75 void *calloc(size_t size
, size_t count
) throw(std::bad_alloc
)
78 if(__builtin_mul_overflow(size
, count
, &bytes
)) {
79 // Multiplication overflowed.
80 throw std::bad_alloc();
82 void *addr
= malloc(bytes
);
83 memset(addr
, 0, bytes
);
87 // compare Allocators for identity
88 virtual bool operator == (const Allocator
&alloc
) const throw();
91 // allocator chooser options
97 static Allocator
&standard(UInt32 request
= normal
);
102 // You'd think that this is operator delete(const T *, Allocator &), but you'd
103 // be wrong. Specialized operator delete is only called during constructor cleanup.
104 // Use this to cleanly destroy things.
107 inline void destroy(T
*obj
, Allocator
&alloc
) throw()
113 // untyped (release memory only, no destructor call)
114 inline void destroy(void *obj
, Allocator
&alloc
) throw()
121 // A mixin class to automagically manage your allocator.
122 // To allow allocation (of your object) from any instance of Allocator,
123 // inherit from CssmHeap. Your users can then create heap instances of your thing by
124 // new (an-allocator) YourClass(...)
126 // new YourClass(...)
127 // for the default allocation source. The beauty is that when someone does a
128 // delete pointer-to-your-instance
129 // then the magic fairies will find the allocator that created the object and ask it
130 // to free the memory (by calling its free() method).
131 // The price of all that glory is memory overhead - typically one pointer per object.
135 void *operator new (size_t size
, Allocator
*alloc
= NULL
) throw(std::bad_alloc
);
136 void operator delete (void *addr
, size_t size
) throw();
137 void operator delete (void *addr
, size_t size
, Allocator
*alloc
) throw();
142 // Here is a version of auto_ptr that works with Allocators. It is designed
143 // to be pretty much a drop-in replacement. It requires an allocator as a constructor
144 // argument, of course.
145 // Note that CssmAutoPtr<void> is perfectly valid, unlike its auto_ptr look-alike.
146 // You can't dereference it, naturally.
151 Allocator
&allocator
;
153 CssmAutoPtr(Allocator
&alloc
= Allocator::standard())
154 : allocator(alloc
), mine(NULL
) { }
155 CssmAutoPtr(Allocator
&alloc
, T
*p
)
156 : allocator(alloc
), mine(p
) { }
158 : allocator(Allocator::standard()), mine(p
) { }
159 template <class T1
> CssmAutoPtr(CssmAutoPtr
<T1
> &src
)
160 : allocator(src
.allocator
), mine(src
.release()) { }
161 template <class T1
> CssmAutoPtr(Allocator
&alloc
, CssmAutoPtr
<T1
> &src
)
162 : allocator(alloc
), mine(src
.release()) { assert(allocator
== src
.allocator
); }
164 ~CssmAutoPtr() { allocator
.free(mine
); }
166 T
*get() const throw() { return mine
; }
167 T
*release() { T
*result
= mine
; mine
= NULL
; return result
; }
168 void reset() { allocator
.free(mine
); mine
= NULL
; }
170 operator T
* () const { return mine
; }
171 T
*operator -> () const { return mine
; }
172 T
&operator * () const { assert(mine
); return *mine
; }
178 // specialization for void (i.e. void *), omitting the troublesome dereferencing ops.
180 class CssmAutoPtr
<void> {
182 Allocator
&allocator
;
184 CssmAutoPtr(Allocator
&alloc
) : allocator(alloc
), mine(NULL
) { }
185 CssmAutoPtr(Allocator
&alloc
, void *p
) : allocator(alloc
), mine(p
) { }
186 template <class T1
> CssmAutoPtr(CssmAutoPtr
<T1
> &src
)
187 : allocator(src
.allocator
), mine(src
.release()) { }
188 template <class T1
> CssmAutoPtr(Allocator
&alloc
, CssmAutoPtr
<T1
> &src
)
189 : allocator(alloc
), mine(src
.release()) { assert(allocator
== src
.allocator
); }
191 ~CssmAutoPtr() { destroy(mine
, allocator
); }
193 void *get() throw() { return mine
; }
194 void *release() { void *result
= mine
; mine
= NULL
; return result
; }
195 void reset() { allocator
.free(mine
); mine
= NULL
; }
203 // Convenience forms of CssmAutoPtr that automatically make their (initial) object.
206 class CssmNewAutoPtr
: public CssmAutoPtr
<T
> {
208 CssmNewAutoPtr(Allocator
&alloc
= Allocator::standard())
209 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T
) { }
212 CssmNewAutoPtr(Allocator
&alloc
, A1
&arg1
) : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
)) { }
214 CssmNewAutoPtr(Allocator
&alloc
, const A1
&arg1
)
215 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
)) { }
217 template <class A1
, class A2
>
218 CssmNewAutoPtr(Allocator
&alloc
, A1
&arg1
, A2
&arg2
)
219 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
220 template <class A1
, class A2
>
221 CssmNewAutoPtr(Allocator
&alloc
, const A1
&arg1
, A2
&arg2
)
222 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
223 template <class A1
, class A2
>
224 CssmNewAutoPtr(Allocator
&alloc
, A1
&arg1
, const A2
&arg2
)
225 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
226 template <class A1
, class A2
>
227 CssmNewAutoPtr(Allocator
&alloc
, const A1
&arg1
, const A2
&arg2
)
228 : CssmAutoPtr
<T
>(alloc
, new(alloc
) T(arg1
, arg2
)) { }
232 } // end namespace Security
236 // Global C++ allocation hooks to use Allocators (global namespace)
238 inline void *operator new (size_t size
, Allocator
&allocator
) throw (std::bad_alloc
)
239 { return allocator
.malloc(size
); }
241 inline void *operator new[] (size_t size
, Allocator
&allocator
) throw (std::bad_alloc
)
242 { return allocator
.malloc(size
); }