]> git.saurik.com Git - apple/icu.git/blame_incremental - icuSources/common/cmemory.c
ICU-511.35.tar.gz
[apple/icu.git] / icuSources / common / cmemory.c
... / ...
CommitLineData
1/*
2******************************************************************************
3*
4* Copyright (C) 2002-2012, International Business Machines
5* Corporation and others. All Rights Reserved.
6*
7******************************************************************************
8*
9* File cmemory.c ICU Heap allocation.
10* All ICU heap allocation, both for C and C++ new of ICU
11* class types, comes through these functions.
12*
13* If you have a need to replace ICU allocation, this is the
14* place to do it.
15*
16* Note that uprv_malloc(0) returns a non-NULL pointer, and
17* that a subsequent free of that pointer value is a NOP.
18*
19******************************************************************************
20*/
21#include "unicode/uclean.h"
22#include "cmemory.h"
23#include "putilimp.h"
24#include "uassert.h"
25#include <stdlib.h>
26
27/* uprv_malloc(0) returns a pointer to this read-only data. */
28static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0};
29
30/* Function Pointers for user-supplied heap functions */
31static const void *pContext;
32static UMemAllocFn *pAlloc;
33static UMemReallocFn *pRealloc;
34static UMemFreeFn *pFree;
35
36/* Flag indicating whether any heap allocations have happened.
37 * Used to prevent changing out the heap functions after allocations have been made */
38static UBool gHeapInUse;
39
40#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
41#include <stdio.h>
42static int n=0;
43static long b=0;
44#endif
45
46#if U_DEBUG
47
48static char gValidMemorySink = 0;
49
50U_CAPI void uprv_checkValidMemory(const void *p, size_t n) {
51 /*
52 * Access the memory to ensure that it's all valid.
53 * Load and save a computed value to try to ensure that the compiler
54 * does not throw away the whole loop.
55 * A thread analyzer might complain about un-mutexed access to gValidMemorySink
56 * which is true but harmless because no one ever uses the value in gValidMemorySink.
57 */
58 const char *s = (const char *)p;
59 char c = gValidMemorySink;
60 size_t i;
61 U_ASSERT(p != NULL);
62 for(i = 0; i < n; ++i) {
63 c ^= s[i];
64 }
65 gValidMemorySink = c;
66}
67
68#endif /* U_DEBUG */
69
70U_CAPI void * U_EXPORT2
71uprv_malloc(size_t s) {
72#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
73#if 1
74 putchar('>');
75 fflush(stdout);
76#else
77 fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr);
78#endif
79#endif
80 if (s > 0) {
81 gHeapInUse = TRUE;
82 if (pAlloc) {
83 return (*pAlloc)(pContext, s);
84 } else {
85 return uprv_default_malloc(s);
86 }
87 } else {
88 return (void *)zeroMem;
89 }
90}
91
92U_CAPI void * U_EXPORT2
93uprv_realloc(void * buffer, size_t size) {
94#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
95 putchar('~');
96 fflush(stdout);
97#endif
98 if (buffer == zeroMem) {
99 return uprv_malloc(size);
100 } else if (size == 0) {
101 if (pFree) {
102 (*pFree)(pContext, buffer);
103 } else {
104 uprv_default_free(buffer);
105 }
106 return (void *)zeroMem;
107 } else {
108 gHeapInUse = TRUE;
109 if (pRealloc) {
110 return (*pRealloc)(pContext, buffer, size);
111 } else {
112 return uprv_default_realloc(buffer, size);
113 }
114 }
115}
116
117U_CAPI void U_EXPORT2
118uprv_free(void *buffer) {
119#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
120 putchar('<');
121 fflush(stdout);
122#endif
123 if (buffer != zeroMem) {
124 if (pFree) {
125 (*pFree)(pContext, buffer);
126 } else {
127 uprv_default_free(buffer);
128 }
129 }
130}
131
132U_CAPI void * U_EXPORT2
133uprv_calloc(size_t num, size_t size) {
134 void *mem = NULL;
135 size *= num;
136 mem = uprv_malloc(size);
137 if (mem) {
138 uprv_memset(mem, 0, size);
139 }
140 return mem;
141}
142
143U_CAPI void U_EXPORT2
144u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status)
145{
146 if (U_FAILURE(*status)) {
147 return;
148 }
149 if (a==NULL || r==NULL || f==NULL) {
150 *status = U_ILLEGAL_ARGUMENT_ERROR;
151 return;
152 }
153 if (gHeapInUse) {
154 *status = U_INVALID_STATE_ERROR;
155 return;
156 }
157 pContext = context;
158 pAlloc = a;
159 pRealloc = r;
160 pFree = f;
161}
162
163
164U_CFUNC UBool cmemory_cleanup(void) {
165 pContext = NULL;
166 pAlloc = NULL;
167 pRealloc = NULL;
168 pFree = NULL;
169 gHeapInUse = FALSE;
170 return TRUE;
171}
172
173
174/*
175 * gHeapInUse
176 * Return True if ICU has allocated any memory.
177 * Used by u_SetMutexFunctions() and similar to verify that ICU has not
178 * been used, that it is in a pristine initial state.
179 */
180U_CFUNC UBool cmemory_inUse() {
181 return gHeapInUse;
182}
183