Line data Source code
1 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 : /*
3 : * lt-mem.c
4 : * Copyright (C) 2011-2012 Akira TAGOH
5 : *
6 : * Authors:
7 : * Akira TAGOH <akira@tagoh.org>
8 : *
9 : * You may distribute under the terms of either the GNU
10 : * Lesser General Public License or the Mozilla Public
11 : * License, as specified in the README file.
12 : */
13 : #ifdef HAVE_CONFIG_H
14 : #include "config.h"
15 : #endif
16 :
17 : #include <stdlib.h>
18 : #include "lt-atomic.h"
19 : #include "lt-mem.h"
20 : #include "lt-messages.h"
21 :
22 : struct _lt_mem_slist_t {
23 : lt_mem_slist_t *next;
24 : lt_pointer_t key;
25 : lt_destroy_func_t func;
26 : };
27 :
28 : lt_mem_slist_t *lt_mem_slist_new (void);
29 : void lt_mem_slist_free (lt_mem_slist_t *list);
30 : lt_mem_slist_t *lt_mem_slist_last (lt_mem_slist_t *list);
31 : lt_mem_slist_t *lt_mem_slist_append (lt_mem_slist_t *list,
32 : lt_pointer_t key,
33 : lt_destroy_func_t func);
34 : lt_mem_slist_t *lt_mem_slist_delete (lt_mem_slist_t *list,
35 : lt_pointer_t *data);
36 : lt_mem_slist_t *lt_mem_slist_delete_link(lt_mem_slist_t *list,
37 : lt_mem_slist_t *link_);
38 : lt_mem_slist_t *lt_mem_slist_find (lt_mem_slist_t *list,
39 : const lt_pointer_t data);
40 :
41 :
42 : /*< private >*/
43 :
44 : /*< protected >*/
45 : lt_mem_slist_t *
46 195048 : lt_mem_slist_new(void)
47 : {
48 195048 : return malloc(sizeof (lt_mem_slist_t));
49 : }
50 :
51 : void
52 0 : lt_mem_slist_free(lt_mem_slist_t *list)
53 : {
54 0 : lt_mem_slist_t *l = list;
55 :
56 0 : while (l) {
57 0 : list = l;
58 0 : l = l->next;
59 0 : free(list);
60 : }
61 0 : }
62 :
63 : lt_mem_slist_t *
64 76874 : lt_mem_slist_last(lt_mem_slist_t *list)
65 : {
66 76874 : if (list) {
67 470408 : while (list->next)
68 316660 : list = list->next;
69 : }
70 :
71 76874 : return list;
72 : }
73 :
74 : lt_mem_slist_t *
75 195048 : lt_mem_slist_append(lt_mem_slist_t *list,
76 : lt_pointer_t key,
77 : lt_destroy_func_t func)
78 : {
79 195048 : lt_mem_slist_t *l = lt_mem_slist_new();
80 : lt_mem_slist_t *last;
81 :
82 195048 : l->key = key;
83 195048 : l->func = func;
84 195048 : l->next = NULL;
85 195048 : if (list) {
86 76874 : last = lt_mem_slist_last(list);
87 76874 : last->next = l;
88 : } else {
89 118174 : list = l;
90 : }
91 :
92 195048 : return list;
93 : }
94 :
95 : lt_mem_slist_t *
96 0 : lt_mem_slist_delete(lt_mem_slist_t *list,
97 : lt_pointer_t *data)
98 : {
99 0 : lt_mem_slist_t *l = list;
100 :
101 0 : while (l) {
102 0 : if (l->key == data) {
103 0 : list = lt_mem_slist_delete_link(list, l);
104 0 : break;
105 : } else {
106 0 : l = l->next;
107 : }
108 : }
109 :
110 0 : return list;
111 : }
112 :
113 : lt_mem_slist_t *
114 104 : lt_mem_slist_delete_link(lt_mem_slist_t *list,
115 : lt_mem_slist_t *link_)
116 : {
117 104 : lt_mem_slist_t *prev = NULL, *l = list;
118 :
119 376 : while (l) {
120 272 : if (l == link_) {
121 104 : if (prev)
122 44 : prev->next = l->next;
123 104 : if (list == l)
124 60 : list = list->next;
125 104 : free(link_);
126 104 : break;
127 : }
128 168 : prev = l;
129 168 : l = l->next;
130 : }
131 :
132 104 : return list;
133 : }
134 :
135 : lt_mem_slist_t *
136 41148 : lt_mem_slist_find(lt_mem_slist_t *list,
137 : const lt_pointer_t data)
138 : {
139 82464 : while (list) {
140 272 : if (list->key == data)
141 104 : break;
142 168 : list = list->next;
143 : }
144 :
145 41148 : return list;
146 : }
147 :
148 : /*< public >*/
149 : lt_pointer_t
150 77130 : lt_mem_alloc_object(size_t size)
151 : {
152 : lt_mem_t *retval;
153 :
154 77130 : lt_return_val_if_fail (size > 0, NULL);
155 :
156 77130 : retval = calloc(1, size);
157 77130 : if (retval) {
158 77130 : retval->ref_count = 1;
159 77130 : retval->refs = NULL;
160 77130 : retval->size = size;
161 : }
162 :
163 77130 : return retval;
164 : }
165 :
166 : lt_pointer_t
167 35314 : lt_mem_ref(lt_mem_t *object)
168 : {
169 35314 : lt_return_val_if_fail (object != NULL, NULL);
170 :
171 35314 : lt_atomic_int_inc((volatile int *)&object->ref_count);
172 :
173 35314 : return object;
174 : }
175 :
176 : void
177 112444 : lt_mem_unref(lt_mem_t *object)
178 : {
179 224888 : lt_return_if_fail (object != NULL);
180 :
181 112444 : if (lt_atomic_int_dec_and_test((volatile int *)&object->ref_count)) {
182 : lt_mem_slist_t *ll, *l;
183 :
184 77130 : if (object->refs) {
185 77070 : ll = object->refs;
186 308040 : while (ll) {
187 153900 : l = ll;
188 153900 : ll = ll->next;
189 153900 : if (l->func)
190 153900 : l->func(l->key);
191 153900 : free(l);
192 : }
193 : }
194 77130 : if (object->weak_pointers) {
195 41044 : ll = object->weak_pointers;
196 123132 : while (ll) {
197 : lt_pointer_t *p;
198 :
199 41044 : l = ll;
200 41044 : ll = ll->next;
201 41044 : p = (lt_pointer_t *)l->key;
202 41044 : *p = NULL;
203 41044 : free(l);
204 : }
205 : }
206 77130 : free(object);
207 : }
208 : }
209 :
210 : void
211 154004 : lt_mem_add_ref(lt_mem_t *object,
212 : lt_pointer_t p,
213 : lt_destroy_func_t func)
214 : {
215 154004 : lt_return_if_fail (object != NULL);
216 154004 : lt_return_if_fail (p != NULL);
217 154004 : lt_return_if_fail (func != NULL);
218 :
219 154004 : object->refs = lt_mem_slist_append(object->refs, p, func);
220 : }
221 :
222 : void
223 76 : lt_mem_remove_ref(lt_mem_t *object,
224 : lt_pointer_t p)
225 : {
226 : lt_mem_slist_t *l;
227 :
228 76 : lt_return_if_fail (object != NULL);
229 76 : lt_return_if_fail (p != NULL);
230 :
231 76 : if ((l = lt_mem_slist_find(object->refs, p)) != NULL) {
232 76 : object->refs = lt_mem_slist_delete_link(object->refs, l);
233 : }
234 : }
235 :
236 : void
237 28 : lt_mem_delete_ref(lt_mem_t *object,
238 : lt_pointer_t p)
239 : {
240 : lt_mem_slist_t *l;
241 :
242 28 : lt_return_if_fail (object != NULL);
243 28 : lt_return_if_fail (p != NULL);
244 :
245 28 : if ((l = lt_mem_slist_find(object->refs, p)) != NULL) {
246 28 : if (l->func)
247 28 : l->func(l->key);
248 28 : object->refs = lt_mem_slist_delete_link(object->refs, l);
249 : }
250 : }
251 :
252 : void
253 41044 : lt_mem_add_weak_pointer(lt_mem_t *object,
254 : lt_pointer_t *p)
255 : {
256 41044 : lt_return_if_fail (object != NULL);
257 41044 : lt_return_if_fail (p != NULL);
258 :
259 41044 : if (!lt_mem_slist_find(object->weak_pointers, p))
260 41044 : object->weak_pointers = lt_mem_slist_append(object->weak_pointers, p, NULL);
261 : }
262 :
263 : void
264 0 : lt_mem_remove_weak_pointer(lt_mem_t *object,
265 : lt_pointer_t *p)
266 : {
267 0 : lt_return_if_fail (object != NULL);
268 0 : lt_return_if_fail (p != NULL);
269 :
270 0 : object->weak_pointers = lt_mem_slist_delete(object->weak_pointers, p);
271 : }
|