WINGs: Added 'const' attribute to function 'WMCreateHashTable'
[wmaker-crm.git] / WINGs / memory.c
blob7f4f0a8560d6a1489cb884dabd7753ac89a0208e
1 /*
2 * Window Maker miscelaneous function library
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
22 #include "wconfig.h"
23 #include "WUtil.h"
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <assert.h>
31 #include <signal.h>
33 #ifdef USE_BOEHM_GC
34 #ifndef GC_DEBUG
35 #define GC_DEBUG
36 #endif /* !GC_DEBUG */
37 #include <gc/gc.h>
38 #endif /* USE_BOEHM_GC */
40 #ifndef False
41 # define False 0
42 #endif
43 #ifndef True
44 # define True 1
45 #endif
47 static void defaultHandler(int bla)
49 if (bla)
50 kill(getpid(), SIGABRT);
51 else
52 exit(1);
55 static waborthandler *aborthandler = defaultHandler;
57 #define wAbort(a) (*aborthandler)(a)
59 waborthandler *wsetabort(waborthandler * handler)
61 waborthandler *old = aborthandler;
63 aborthandler = handler;
65 return old;
68 static int Aborting = 0; /* if we're in the middle of an emergency exit */
70 static WMHashTable *table = NULL;
72 void *wmalloc(size_t size)
74 void *tmp;
76 assert(size > 0);
78 #ifdef USE_BOEHM_GC
79 tmp = GC_MALLOC(size);
80 #else
81 tmp = malloc(size);
82 #endif
83 if (tmp == NULL) {
84 wwarning("malloc() failed. Retrying after 2s.");
85 sleep(2);
86 #ifdef USE_BOEHM_GC
87 tmp = GC_MALLOC(size);
88 #else
89 tmp = malloc(size);
90 #endif
91 if (tmp == NULL) {
92 if (Aborting) {
93 fputs("Really Bad Error: recursive malloc() failure.", stderr);
94 exit(-1);
95 } else {
96 wfatal("virtual memory exhausted");
97 Aborting = 1;
98 wAbort(False);
102 memset(tmp, 0, size);
103 return tmp;
106 void *wrealloc(void *ptr, size_t newsize)
108 void *nptr;
110 if (!ptr) {
111 nptr = wmalloc(newsize);
112 } else if (newsize == 0) {
113 wfree(ptr);
114 nptr = NULL;
115 } else {
116 #ifdef USE_BOEHM_GC
117 nptr = GC_REALLOC(ptr, newsize);
118 #else
119 nptr = realloc(ptr, newsize);
120 #endif
121 if (nptr == NULL) {
122 wwarning("realloc() failed. Retrying after 2s.");
123 sleep(2);
124 #ifdef USE_BOEHM_GC
125 nptr = GC_REALLOC(ptr, newsize);
126 #else
127 nptr = realloc(ptr, newsize);
128 #endif
129 if (nptr == NULL) {
130 if (Aborting) {
131 fputs("Really Bad Error: recursive realloc() failure.", stderr);
132 exit(-1);
133 } else {
134 wfatal("virtual memory exhausted");
135 Aborting = 1;
136 wAbort(False);
141 return nptr;
144 void *wretain(void *ptr)
146 int *refcount;
148 if (!table) {
149 table = WMCreateHashTable(WMIntHashCallbacks);
152 refcount = WMHashGet(table, ptr);
153 if (!refcount) {
154 refcount = wmalloc(sizeof(int));
155 *refcount = 1;
156 WMHashInsert(table, ptr, refcount);
157 #ifdef VERBOSE
158 printf("== %i (%p)\n", *refcount, ptr);
159 #endif
160 } else {
161 (*refcount)++;
162 #ifdef VERBOSE
163 printf("+ %i (%p)\n", *refcount, ptr);
164 #endif
167 return ptr;
170 void wfree(void *ptr)
172 if (ptr)
173 #ifdef USE_BOEHM_GC
174 /* This should eventually be removed, once the criss-cross
175 * of wmalloc()d memory being free()d, malloc()d memory being
176 * wfree()d, various misuses of calling wfree() on objects
177 * allocated by libc malloc() and calling libc free() on
178 * objects allocated by Boehm GC (think external libraries)
179 * is cleaned up.
181 if (GC_base(ptr) != 0)
182 GC_FREE(ptr);
183 else
184 free(ptr);
185 #else
186 free(ptr);
187 #endif
188 ptr = NULL;
191 void wrelease(void *ptr)
193 int *refcount;
195 refcount = WMHashGet(table, ptr);
196 if (!refcount) {
197 wwarning("trying to release unexisting data %p", ptr);
198 } else {
199 (*refcount)--;
200 if (*refcount < 1) {
201 #ifdef VERBOSE
202 printf("RELEASING %p\n", ptr);
203 #endif
204 WMHashRemove(table, ptr);
205 wfree(refcount);
206 wfree(ptr);
208 #ifdef VERBOSE
209 else {
210 printf("- %i (%p)\n", *refcount, ptr);
212 #endif