VirtualBox

source: vbox/trunk/include/iprt/mem.h@ 28536

Last change on this file since 28536 was 28504, checked in by vboxsync, 15 years ago

iprt/mem.h: added note about electric fence

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.9 KB
Line 
1/** @file
2 * IPRT - Memory Management and Manipulation.
3 */
4
5/*
6 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 *
25 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
26 * Clara, CA 95054 USA or visit http://www.sun.com if you need
27 * additional information or have any questions.
28 */
29
30#ifndef ___iprt_mem_h
31#define ___iprt_mem_h
32
33
34#include <iprt/cdefs.h>
35#include <iprt/types.h>
36#ifdef __cplusplus /** @todo remove when spitting. */
37# include <iprt/cpp/autores.h>
38#endif
39
40
41#ifdef IN_RC
42# error "There are no RTMem APIs available Guest Context!"
43#endif
44
45
46/** @defgroup grp_rt_mem RTMem - Memory Management and Manipulation
47 * @ingroup grp_rt
48 * @{
49 */
50
51RT_C_DECLS_BEGIN
52
53/** @def RTMEM_ALIGNMENT
54 * The alignment of the memory blocks returned by RTMemAlloc(), RTMemAllocZ(),
55 * RTMemRealloc(), RTMemTmpAlloc() and RTMemTmpAllocZ() for allocations greater
56 * than RTMEM_ALIGNMENT.
57 *
58 * @note This alignment is not forced if the electric fence is active!
59 */
60#define RTMEM_ALIGNMENT 8
61
62/**
63 * Allocates temporary memory.
64 *
65 * Temporary memory blocks are used for not too large memory blocks which
66 * are believed not to stick around for too long. Using this API instead
67 * of RTMemAlloc() not only gives the heap manager room for optimization
68 * but makes the code easier to read.
69 *
70 * @returns Pointer to the allocated memory.
71 * @returns NULL on failure.
72 * @param cb Size in bytes of the memory block to allocated.
73 */
74RTDECL(void *) RTMemTmpAlloc(size_t cb) RT_NO_THROW;
75
76/**
77 * Allocates zero'ed temporary memory.
78 *
79 * Same as RTMemTmpAlloc() but the memory will be zero'ed.
80 *
81 * @returns Pointer to the allocated memory.
82 * @returns NULL on failure.
83 * @param cb Size in bytes of the memory block to allocated.
84 */
85RTDECL(void *) RTMemTmpAllocZ(size_t cb) RT_NO_THROW;
86
87/**
88 * Free temporary memory.
89 *
90 * @param pv Pointer to memory block.
91 */
92RTDECL(void) RTMemTmpFree(void *pv) RT_NO_THROW;
93
94
95/**
96 * Allocates memory.
97 *
98 * @returns Pointer to the allocated memory.
99 * @returns NULL on failure.
100 * @param cb Size in bytes of the memory block to allocated.
101 */
102RTDECL(void *) RTMemAlloc(size_t cb) RT_NO_THROW;
103
104/**
105 * Allocates zero'ed memory.
106 *
107 * Instead of memset(pv, 0, sizeof()) use this when you want zero'ed
108 * memory. This keeps the code smaller and the heap can skip the memset
109 * in about 0.42% of calls :-).
110 *
111 * @returns Pointer to the allocated memory.
112 * @returns NULL on failure.
113 * @param cb Size in bytes of the memory block to allocated.
114 */
115RTDECL(void *) RTMemAllocZ(size_t cb) RT_NO_THROW;
116
117/**
118 * Wrapper around RTMemAlloc for automatically aligning variable sized
119 * allocations so that the various electric fence heaps works correctly.
120 *
121 * @returns See RTMemAlloc.
122 * @param cbUnaligned The unaligned size.
123 */
124RTDECL(void *) RTMemAllocVar(size_t cbUnaligned);
125
126/**
127 * Wrapper around RTMemAllocZ for automatically aligning variable sized
128 * allocations so that the various electric fence heaps works correctly.
129 *
130 * @returns See RTMemAllocZ.
131 * @param cbUnaligned The unaligned size.
132 */
133RTDECL(void *) RTMemAllocZVar(size_t cbUnaligned);
134
135/**
136 * Duplicates a chunk of memory into a new heap block.
137 *
138 * @returns New heap block with the duplicate data.
139 * @returns NULL if we're out of memory.
140 * @param pvSrc The memory to duplicate.
141 * @param cb The amount of memory to duplicate.
142 */
143RTDECL(void *) RTMemDup(const void *pvSrc, size_t cb) RT_NO_THROW;
144
145/**
146 * Duplicates a chunk of memory into a new heap block with some
147 * additional zeroed memory.
148 *
149 * @returns New heap block with the duplicate data.
150 * @returns NULL if we're out of memory.
151 * @param pvSrc The memory to duplicate.
152 * @param cbSrc The amount of memory to duplicate.
153 * @param cbExtra The amount of extra memory to allocate and zero.
154 */
155RTDECL(void *) RTMemDupEx(const void *pvSrc, size_t cbSrc, size_t cbExtra) RT_NO_THROW;
156
157/**
158 * Reallocates memory.
159 *
160 * @returns Pointer to the allocated memory.
161 * @returns NULL on failure.
162 * @param pvOld The memory block to reallocate.
163 * @param cbNew The new block size (in bytes).
164 */
165RTDECL(void *) RTMemRealloc(void *pvOld, size_t cbNew) RT_NO_THROW;
166
167/**
168 * Frees memory.
169 *
170 * @param pv Pointer to memory block.
171 */
172RTDECL(void) RTMemFree(void *pv) RT_NO_THROW;
173
174/**
175 * Allocates memory which may contain code.
176 *
177 * @returns Pointer to the allocated memory.
178 * @returns NULL on failure.
179 * @param cb Size in bytes of the memory block to allocate.
180 */
181RTDECL(void *) RTMemExecAlloc(size_t cb) RT_NO_THROW;
182
183/**
184 * Free executable/read/write memory allocated by RTMemExecAlloc().
185 *
186 * @param pv Pointer to memory block.
187 */
188RTDECL(void) RTMemExecFree(void *pv) RT_NO_THROW;
189
190#if defined(IN_RING0) && defined(RT_ARCH_AMD64) && defined(RT_OS_LINUX)
191/**
192 * Donate read+write+execute memory to the exec heap.
193 *
194 * This API is specific to AMD64 and Linux/GNU. A kernel module that desires to
195 * use RTMemExecAlloc on AMD64 Linux/GNU will have to donate some statically
196 * allocated memory in the module if it wishes for GCC generated code to work.
197 * GCC can only generate modules that work in the address range ~2GB to ~0
198 * currently.
199 *
200 * The API only accept one single donation.
201 *
202 * @returns IPRT status code.
203 * @param pvMemory Pointer to the memory block.
204 * @param cb The size of the memory block.
205 */
206RTR0DECL(int) RTR0MemExecDonate(void *pvMemory, size_t cb) RT_NO_THROW;
207#endif /* R0+AMD64+LINUX */
208
209/**
210 * Allocate page aligned memory.
211 *
212 * @returns Pointer to the allocated memory.
213 * @returns NULL if we're out of memory.
214 * @param cb Size of the memory block. Will be rounded up to page size.
215 */
216RTDECL(void *) RTMemPageAlloc(size_t cb) RT_NO_THROW;
217
218/**
219 * Allocate zero'ed page aligned memory.
220 *
221 * @returns Pointer to the allocated memory.
222 * @returns NULL if we're out of memory.
223 * @param cb Size of the memory block. Will be rounded up to page size.
224 */
225RTDECL(void *) RTMemPageAllocZ(size_t cb) RT_NO_THROW;
226
227/**
228 * Free a memory block allocated with RTMemPageAlloc() or RTMemPageAllocZ().
229 *
230 * @param pv Pointer to the block as it was returned by the allocation function.
231 * NULL will be ignored.
232 * @param cb The allocation size. Will be rounded up to page size.
233 * Ignored if @a pv is NULL.
234 */
235RTDECL(void) RTMemPageFree(void *pv, size_t cb) RT_NO_THROW;
236
237/** Page level protection flags for RTMemProtect().
238 * @{
239 */
240/** No access at all. */
241#define RTMEM_PROT_NONE 0
242/** Read access. */
243#define RTMEM_PROT_READ 1
244/** Write access. */
245#define RTMEM_PROT_WRITE 2
246/** Execute access. */
247#define RTMEM_PROT_EXEC 4
248/** @} */
249
250/**
251 * Change the page level protection of a memory region.
252 *
253 * @returns iprt status code.
254 * @param pv Start of the region. Will be rounded down to nearest page boundary.
255 * @param cb Size of the region. Will be rounded up to the nearest page boundary.
256 * @param fProtect The new protection, a combination of the RTMEM_PROT_* defines.
257 */
258RTDECL(int) RTMemProtect(void *pv, size_t cb, unsigned fProtect) RT_NO_THROW;
259
260
261#ifdef IN_RING0
262
263/**
264 * Allocates physical contiguous memory (below 4GB).
265 * The allocation is page aligned and the content is undefined.
266 *
267 * @returns Pointer to the memory block. This is page aligned.
268 * @param pPhys Where to store the physical address.
269 * @param cb The allocation size in bytes. This is always
270 * rounded up to PAGE_SIZE.
271 */
272RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb) RT_NO_THROW;
273
274/**
275 * Frees memory allocated ysing RTMemContAlloc().
276 *
277 * @param pv Pointer to return from RTMemContAlloc().
278 * @param cb The cb parameter passed to RTMemContAlloc().
279 */
280RTR0DECL(void) RTMemContFree(void *pv, size_t cb) RT_NO_THROW;
281
282/**
283 * Copy memory from an user mode buffer into a kernel buffer.
284 *
285 * @retval VINF_SUCCESS on success.
286 * @retval VERR_ACCESS_DENIED on error.
287 *
288 * @param pvDst The kernel mode destination address.
289 * @param R3PtrSrc The user mode source address.
290 * @param cb The number of bytes to copy.
291 */
292RTR0DECL(int) RTR0MemUserCopyFrom(void *pvDst, RTR3PTR R3PtrSrc, size_t cb);
293
294/**
295 * Copy memory from a kernel buffer into a user mode one.
296 *
297 * @retval VINF_SUCCESS on success.
298 * @retval VERR_ACCESS_DENIED on error.
299 *
300 * @param R3PtrDst The user mode destination address.
301 * @param pvSrc The kernel mode source address.
302 * @param cb The number of bytes to copy.
303 */
304RTR0DECL(int) RTR0MemUserCopyTo(RTR3PTR R3PtrDst, void const *pvSrc, size_t cb);
305
306/**
307 * Tests if the specified address is in the user addressable range.
308 *
309 * This function does not check whether the memory at that address is accessible
310 * or anything of that sort, only if the address it self is in the user mode
311 * range.
312 *
313 * @returns true if it's in the user addressable range. false if not.
314 * @param R3Ptr The user mode pointer to test.
315 *
316 * @remarks Some systems may have overlapping kernel and user address ranges.
317 * One prominent example of this is the x86 version of Mac OS X. Use
318 * RTR0MemAreKrnlAndUsrDifferent() to check.
319 */
320RTR0DECL(bool) RTR0MemUserIsValidAddr(RTR3PTR R3Ptr);
321
322/**
323 * Tests if the specified address is in the kernel mode range.
324 *
325 * This function does not check whether the memory at that address is accessible
326 * or anything of that sort, only if the address it self is in the kernel mode
327 * range.
328 *
329 * @returns true if it's in the kernel range. false if not.
330 * @param pv The alleged kernel mode pointer.
331 *
332 * @remarks Some systems may have overlapping kernel and user address ranges.
333 * One prominent example of this is the x86 version of Mac OS X. Use
334 * RTR0MemAreKrnlAndUsrDifferent() to check.
335 */
336RTR0DECL(bool) RTR0MemKernelIsValidAddr(void *pv);
337
338/**
339 * Are user mode and kernel mode address ranges distinctly different.
340 *
341 * This determins whether RTR0MemKernelIsValidAddr and RTR0MemUserIsValidAddr
342 * can be used for deciding whether some arbitrary address is a user mode or a
343 * kernel mode one.
344 *
345 * @returns true if they are, false if not.
346 */
347RTR0DECL(bool) RTR0MemAreKrnlAndUsrDifferent(void);
348
349#endif /* IN_RING0 */
350
351
352/** @name Electrical Fence Version of some APIs.
353 * @{
354 */
355
356/**
357 * Same as RTMemTmpAlloc() except that it's fenced.
358 *
359 * @returns Pointer to the allocated memory.
360 * @returns NULL on failure.
361 * @param cb Size in bytes of the memory block to allocate.
362 */
363RTDECL(void *) RTMemEfTmpAlloc(size_t cb, RT_SRC_POS_DECL) RT_NO_THROW;
364
365/**
366 * Same as RTMemTmpAllocZ() except that it's fenced.
367 *
368 * @returns Pointer to the allocated memory.
369 * @returns NULL on failure.
370 * @param cb Size in bytes of the memory block to allocate.
371 */
372RTDECL(void *) RTMemEfTmpAllocZ(size_t cb, RT_SRC_POS_DECL) RT_NO_THROW;
373
374/**
375 * Same as RTMemTmpFree() except that it's for fenced memory.
376 *
377 * @param pv Pointer to memory block.
378 */
379RTDECL(void) RTMemEfTmpFree(void *pv, RT_SRC_POS_DECL) RT_NO_THROW;
380
381/**
382 * Same as RTMemAlloc() except that it's fenced.
383 *
384 * @returns Pointer to the allocated memory. Free with RTMemEfFree().
385 * @returns NULL on failure.
386 * @param cb Size in bytes of the memory block to allocate.
387 */
388RTDECL(void *) RTMemEfAlloc(size_t cb, RT_SRC_POS_DECL) RT_NO_THROW;
389
390/**
391 * Same as RTMemAllocZ() except that it's fenced.
392 *
393 * @returns Pointer to the allocated memory.
394 * @returns NULL on failure.
395 * @param cb Size in bytes of the memory block to allocate.
396 */
397RTDECL(void *) RTMemEfAllocZ(size_t cb, RT_SRC_POS_DECL) RT_NO_THROW;
398
399/**
400 * Same as RTMemAllocVar() except that it's fenced.
401 *
402 * @returns Pointer to the allocated memory. Free with RTMemEfFree().
403 * @returns NULL on failure.
404 * @param cbUnaligned Size in bytes of the memory block to allocate.
405 */
406RTDECL(void *) RTMemEfAllocVar(size_t cbUnaligned, RT_SRC_POS_DECL) RT_NO_THROW;
407
408/**
409 * Same as RTMemAllocZVar() except that it's fenced.
410 *
411 * @returns Pointer to the allocated memory.
412 * @returns NULL on failure.
413 * @param cbUnaligned Size in bytes of the memory block to allocate.
414 */
415RTDECL(void *) RTMemEfAllocZVar(size_t cbUnaligned, RT_SRC_POS_DECL) RT_NO_THROW;
416
417/**
418 * Same as RTMemRealloc() except that it's fenced.
419 *
420 * @returns Pointer to the allocated memory.
421 * @returns NULL on failure.
422 * @param pvOld The memory block to reallocate.
423 * @param cbNew The new block size (in bytes).
424 */
425RTDECL(void *) RTMemEfRealloc(void *pvOld, size_t cbNew, RT_SRC_POS_DECL) RT_NO_THROW;
426
427/**
428 * Free memory allocated by any of the RTMemEf* allocators.
429 *
430 * @param pv Pointer to memory block.
431 */
432RTDECL(void) RTMemEfFree(void *pv, RT_SRC_POS_DECL) RT_NO_THROW;
433
434/**
435 * Same as RTMemDup() except that it's fenced.
436 *
437 * @returns New heap block with the duplicate data.
438 * @returns NULL if we're out of memory.
439 * @param pvSrc The memory to duplicate.
440 * @param cb The amount of memory to duplicate.
441 */
442RTDECL(void *) RTMemEfDup(const void *pvSrc, size_t cb, RT_SRC_POS_DECL) RT_NO_THROW;
443
444/**
445 * Same as RTMemEfDupEx except that it's fenced.
446 *
447 * @returns New heap block with the duplicate data.
448 * @returns NULL if we're out of memory.
449 * @param pvSrc The memory to duplicate.
450 * @param cbSrc The amount of memory to duplicate.
451 * @param cbExtra The amount of extra memory to allocate and zero.
452 */
453RTDECL(void *) RTMemEfDupEx(const void *pvSrc, size_t cbSrc, size_t cbExtra, RT_SRC_POS_DECL) RT_NO_THROW;
454
455/** @def RTMEM_WRAP_TO_EF_APIS
456 * Define RTMEM_WRAP_TO_EF_APIS to wrap RTMem APIs to RTMemEf APIs.
457 */
458#if defined(RTMEM_WRAP_TO_EF_APIS) && defined(IN_RING3) && !defined(RTMEM_NO_WRAP_TO_EF_APIS)
459# define RTMemTmpAlloc(cb) RTMemEfTmpAlloc((cb), RT_SRC_POS)
460# define RTMemTmpAllocZ(cb) RTMemEfTmpAllocZ((cb), RT_SRC_POS)
461# define RTMemTmpFree(pv) RTMemEfTmpFree((pv), RT_SRC_POS)
462# define RTMemAlloc(cb) RTMemEfAlloc((cb), RT_SRC_POS)
463# define RTMemAllocZ(cb) RTMemEfAllocZ((cb), RT_SRC_POS)
464# define RTMemAllocVar(cbUnaligned) RTMemEfAllocVar((cbUnaligned), RT_SRC_POS)
465# define RTMemAllocZVar(cbUnaligned) RTMemEfAllocZVar((cbUnaligned), RT_SRC_POS)
466# define RTMemRealloc(pvOld, cbNew) RTMemEfRealloc((pvOld), (cbNew), RT_SRC_POS)
467# define RTMemFree(pv) RTMemEfFree((pv), RT_SRC_POS)
468# define RTMemDup(pvSrc, cb) RTMemEfDup((pvSrc), (cb), RT_SRC_POS)
469# define RTMemDupEx(pvSrc, cbSrc, cbExtra) RTMemEfDupEx((pvSrc), (cbSrc), (cbExtra), RT_SRC_POS)
470#endif
471#ifdef DOXYGEN_RUNNING
472# define RTMEM_WRAP_TO_EF_APIS
473#endif
474
475/**
476 * Fenced drop-in replacement for RTMemTmpAlloc.
477 * @copydoc RTMemTmpAlloc
478 */
479RTDECL(void *) RTMemEfTmpAllocNP(size_t cb) RT_NO_THROW;
480
481/**
482 * Fenced drop-in replacement for RTMemTmpAllocZ.
483 * @copydoc RTMemTmpAllocZ
484 */
485RTDECL(void *) RTMemEfTmpAllocZNP(size_t cb) RT_NO_THROW;
486
487/**
488 * Fenced drop-in replacement for RTMemTmpFree.
489 * @copydoc RTMemTmpFree
490 */
491RTDECL(void) RTMemEfTmpFreeNP(void *pv) RT_NO_THROW;
492
493/**
494 * Fenced drop-in replacement for RTMemAlloc.
495 * @copydoc RTMemAlloc
496 */
497RTDECL(void *) RTMemEfAllocNP(size_t cb) RT_NO_THROW;
498
499/**
500 * Fenced drop-in replacement for RTMemAllocZ.
501 * @copydoc RTMemAllocZ
502 */
503RTDECL(void *) RTMemEfAllocZNP(size_t cb) RT_NO_THROW;
504
505/**
506 * Fenced drop-in replacement for RTMemAllocVar
507 * @copydoc RTMemAllocVar
508 */
509RTDECL(void *) RTMemEfAllocVarNP(size_t cbUnaligned) RT_NO_THROW;
510
511/**
512 * Fenced drop-in replacement for RTMemAllocZVar.
513 * @copydoc RTMemAllocZVar
514 */
515RTDECL(void *) RTMemEfAllocZVarNP(size_t cbUnaligned) RT_NO_THROW;
516
517/**
518 * Fenced drop-in replacement for RTMemRealloc.
519 * @copydoc RTMemRealloc
520 */
521RTDECL(void *) RTMemEfReallocNP(void *pvOld, size_t cbNew) RT_NO_THROW;
522
523/**
524 * Fenced drop-in replacement for RTMemFree.
525 * @copydoc RTMemFree
526 */
527RTDECL(void) RTMemEfFreeNP(void *pv) RT_NO_THROW;
528
529/**
530 * Fenced drop-in replacement for RTMemDupEx.
531 * @copydoc RTMemDupEx
532 */
533RTDECL(void *) RTMemEfDupNP(const void *pvSrc, size_t cb) RT_NO_THROW;
534
535/**
536 * Fenced drop-in replacement for RTMemDupEx.
537 * @copydoc RTMemDupEx
538 */
539RTDECL(void *) RTMemEfDupExNP(const void *pvSrc, size_t cbSrc, size_t cbExtra) RT_NO_THROW;
540
541/** @} */
542
543RT_C_DECLS_END
544
545
546#ifdef __cplusplus /** @todo Split this out into iprt/cpp/mem.h! */
547# include <iprt/assert.h>
548
549/**
550 * Template function wrapping RTMemFree to get the correct Destruct
551 * signature for RTAutoRes.
552 *
553 * We can't use a more complex template here, because the g++ on RHEL 3
554 * chokes on it with an internal compiler error.
555 *
556 * @tparam T The data type that's being managed.
557 * @param aMem Pointer to the memory that should be free.
558 */
559template <class T>
560inline void RTMemAutoDestructor(T *aMem) RT_NO_THROW
561{
562 RTMemFree(aMem);
563}
564
565
566/**
567 * RTMemAutoPtr allocator which uses RTMemTmpAlloc().
568 *
569 * @returns Allocated memory on success, NULL on failure.
570 * @param pvOld What to reallocate, shall always be NULL.
571 * @param cbNew The amount of memory to allocate (in bytes).
572 */
573inline void *RTMemTmpAutoAllocator(void *pvOld, size_t cbNew) RT_NO_THROW
574{
575 AssertReturn(!pvOld, NULL);
576 return RTMemTmpAlloc(cbNew);
577}
578
579
580/**
581 * Template function wrapping RTMemTmpFree to get the correct Destruct
582 * signature for RTAutoRes.
583 *
584 * We can't use a more complex template here, because the g++ on RHEL 3
585 * chokes on it with an internal compiler error.
586 *
587 * @tparam T The data type that's being managed.
588 * @param aMem Pointer to the memory that should be free.
589 */
590template <class T>
591inline void RTMemTmpAutoDestructor(T *aMem) RT_NO_THROW
592{
593 RTMemTmpFree(aMem);
594}
595
596
597/**
598 * Template function wrapping RTMemEfFree to get the correct Destruct
599 * signature for RTAutoRes.
600 *
601 * We can't use a more complex template here, because the g++ on RHEL 3
602 * chokes on it with an internal compiler error.
603 *
604 * @tparam T The data type that's being managed.
605 * @param aMem Pointer to the memory that should be free.
606 */
607template <class T>
608inline void RTMemEfAutoFree(T *aMem) RT_NO_THROW
609{
610 RTMemEfFreeNP(aMem);
611}
612
613
614/**
615 * Template function wrapping NULL to get the correct NilRes signature
616 * for RTAutoRes.
617 *
618 * @tparam T The data type that's being managed.
619 * @returns NULL with the right type.
620 */
621template <class T>
622inline T * RTMemAutoNil(void) RT_NO_THROW
623{
624 return (T *)(NULL);
625}
626
627
628/**
629 * An auto pointer-type template class for managing memory allocating
630 * via C APIs like RTMem (the default).
631 *
632 * The main purpose of this class is to automatically free memory that
633 * isn't explicitly used (release()'ed) when the object goes out of scope.
634 *
635 * As an additional service it can also make the allocations and
636 * reallocations for you if you like, but it can also take of memory
637 * you hand it.
638 *
639 * @tparam T The data type to manage allocations for.
640 * @tparam Destruct The function to be used to free the resource.
641 * This will default to RTMemFree.
642 * @tparam Allocator The function to be used to allocate or reallocate
643 * the managed memory.
644 * This is standard realloc() like stuff, so it's possible
645 * to support simple allocation without actually having
646 * to support reallocating memory if that's a problem.
647 * This will default to RTMemRealloc.
648 */
649template <class T, void Destruct(T *) = RTMemAutoDestructor<T>, void *Allocator(void *, size_t) = RTMemRealloc >
650class RTMemAutoPtr
651 : public RTAutoRes<T *, Destruct, RTMemAutoNil<T> >
652{
653public:
654 /**
655 * Constructor.
656 *
657 * @param aPtr Memory pointer to manage. Defaults to NULL.
658 */
659 RTMemAutoPtr(T *aPtr = NULL)
660 : RTAutoRes<T *, Destruct, RTMemAutoNil<T> >(aPtr)
661 {
662 }
663
664 /**
665 * Constructor that allocates memory.
666 *
667 * @param a_cElements The number of elements (of the data type) to allocate.
668 * @param a_fZeroed Whether the memory should be memset with zeros after
669 * the allocation. Defaults to false.
670 */
671 RTMemAutoPtr(size_t a_cElements, bool a_fZeroed = false)
672 : RTAutoRes<T *, Destruct, RTMemAutoNil<T> >((T *)Allocator(NULL, a_cElements * sizeof(T)))
673 {
674 if (a_fZeroed && RT_LIKELY(this->get() != NULL))
675 memset(this->get(), '\0', a_cElements * sizeof(T));
676 }
677
678 /**
679 * Free current memory and start managing aPtr.
680 *
681 * @param aPtr Memory pointer to manage.
682 */
683 RTMemAutoPtr &operator=(T *aPtr)
684 {
685 this->RTAutoRes<T *, Destruct, RTMemAutoNil<T> >::operator=(aPtr);
686 return *this;
687 }
688
689 /**
690 * Dereference with * operator.
691 */
692 T &operator*()
693 {
694 return *this->get();
695 }
696
697 /**
698 * Dereference with -> operator.
699 */
700 T *operator->()
701 {
702 return this->get();
703 }
704
705 /**
706 * Accessed with the subscript operator ([]).
707 *
708 * @returns Reference to the element.
709 * @param a_i The element to access.
710 */
711 T &operator[](size_t a_i)
712 {
713 return this->get()[a_i];
714 }
715
716 /**
717 * Allocates memory and start manage it.
718 *
719 * Any previously managed memory will be freed before making
720 * the new allocation.
721 *
722 * @returns Success indicator.
723 * @retval true if the new allocation succeeds.
724 * @retval false on failure, no memory is associated with the object.
725 *
726 * @param a_cElements The number of elements (of the data type) to allocate.
727 * This defaults to 1.
728 * @param a_fZeroed Whether the memory should be memset with zeros after
729 * the allocation. Defaults to false.
730 */
731 bool alloc(size_t a_cElements = 1, bool a_fZeroed = false)
732 {
733 this->reset(NULL);
734 T *pNewMem = (T *)Allocator(NULL, a_cElements * sizeof(T));
735 if (a_fZeroed && RT_LIKELY(pNewMem != NULL))
736 memset(pNewMem, '\0', a_cElements * sizeof(T));
737 this->reset(pNewMem);
738 return pNewMem != NULL;
739 }
740
741 /**
742 * Reallocate or allocates the memory resource.
743 *
744 * Free the old value if allocation fails.
745 *
746 * The content of any additional memory that was allocated is
747 * undefined when using the default allocator.
748 *
749 * @returns Success indicator.
750 * @retval true if the new allocation succeeds.
751 * @retval false on failure, no memory is associated with the object.
752 *
753 * @param a_cElements The new number of elements (of the data type) to
754 * allocate. The size of the allocation is the number of
755 * elements times the size of the data type - this is
756 * currently what's passed down to the Allocator.
757 * This defaults to 1.
758 */
759 bool realloc(size_t a_cElements = 1)
760 {
761 T *aNewValue = (T *)Allocator(this->get(), a_cElements * sizeof(T));
762 if (RT_LIKELY(aNewValue != NULL))
763 this->release();
764 /* We want this both if aNewValue is non-NULL and if it is NULL. */
765 this->reset(aNewValue);
766 return aNewValue != NULL;
767 }
768};
769
770
771#endif /* __cplusplus */
772
773
774/** @} */
775
776
777#endif
778
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette