Browse code

wrapper memory functions transformed to macros (better debugging), modified message allocation philosophy in message queues and updated documentation

Vaclav Kubart authored on 14/11/2005 08:35:52
Showing 21 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,46 @@
0
+<?xml version="1.0" encoding="UTF-8"?>
1
+
2
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
3
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
4
+
5
+<refentry id="cds_free_ptr"> <!-- ID for references -->
6
+
7
+<refmeta>
8
+<refentrytitle>cds_free_ptr</refentrytitle> <!-- title shown in references -->
9
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
10
+
11
+<refnamediv>
12
+<refname>cds_free_ptr</refname> <!-- function name -->
13
+<refpurpose>pointer to cds_free function independent on cds_free
14
+implementation (macro, ...)</refpurpose> <!-- short function description -->
15
+</refnamediv>
16
+
17
+<refsynopsisdiv><funcsynopsis>
18
+<funcsynopsisinfo>
19
+#include &lt;cds/memory.h&gt; <!-- included headers -->
20
+</funcsynopsisinfo>
21
+
22
+<funcprototype> <!-- function prototype -->
23
+  <funcdef>void <function>cds_free_ptr</function></funcdef>
24
+  <paramdef>void *<parameter>ptr</parameter></paramdef>
25
+</funcprototype>
26
+
27
+</funcsynopsis></refsynopsisdiv>
28
+
29
+<refsect1><title>Description</title>
30
+<para>Pointer to memory deallocation function. It is independent on
31
+<function>cds_free</function> implementation.
32
+<!-- detailed description -->
33
+</para>
34
+
35
+</refsect1>
36
+
37
+<refsect1><title>See Also</title>
38
+<para>
39
+<xref linkend="cds_free"/>
40
+<!-- references to other pages -->
41
+</para>
42
+</refsect1>
43
+
44
+</refentry> 
45
+
... ...
@@ -20,8 +20,8 @@
20 20
 </funcsynopsisinfo>
21 21
 
22 22
 <funcprototype> <!-- function prototype -->
23
-  <funcdef>int <function>cds_malloc</function></funcdef>
24
-  <paramdef>int <parameter>size</parameter></paramdef>
23
+  <funcdef>void *<function>cds_malloc</function></funcdef>
24
+  <paramdef>unsigned int <parameter>size</parameter></paramdef>
25 25
 </funcprototype>
26 26
 
27 27
 </funcsynopsis></refsynopsisdiv>
28 28
new file mode 100644
... ...
@@ -0,0 +1,46 @@
0
+<?xml version="1.0" encoding="UTF-8"?>
1
+
2
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
3
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
4
+
5
+<refentry id="cds_malloc_ptr"> <!-- ID for references -->
6
+
7
+<refmeta>
8
+<refentrytitle>cds_malloc_ptr</refentrytitle> <!-- title shown in references -->
9
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
10
+
11
+<refnamediv>
12
+<refname>cds_malloc_ptr</refname> <!-- function name -->
13
+<refpurpose>pointer to cds_malloc function independent on cds_malloc
14
+implementation (macro, ...)</refpurpose> <!-- short function description -->
15
+</refnamediv>
16
+
17
+<refsynopsisdiv><funcsynopsis>
18
+<funcsynopsisinfo>
19
+#include &lt;cds/memory.h&gt; <!-- included headers -->
20
+</funcsynopsisinfo>
21
+
22
+<funcprototype> <!-- function prototype -->
23
+  <funcdef>void *<function>cds_malloc_ptr</function></funcdef>
24
+  <paramdef>unsigned int <parameter>size</parameter></paramdef>
25
+</funcprototype>
26
+
27
+</funcsynopsis></refsynopsisdiv>
28
+
29
+<refsect1><title>Description</title>
30
+<para>Pointer to memory allocation function. It is independent on
31
+<function>cds_malloc</function> implementation.
32
+<!-- detailed description -->
33
+</para>
34
+
35
+</refsect1>
36
+
37
+<refsect1><title>See Also</title>
38
+<para>
39
+<xref linkend="cds_malloc"/>
40
+<!-- references to other pages -->
41
+</para>
42
+</refsect1>
43
+
44
+</refentry> 
45
+
... ...
@@ -32,23 +32,17 @@
32 32
 if they are allocated implicitly, it is freed together with message. Thus simple
33 33
 data strutures are deallocated automaticaly in both cases. There might be a
34 34
 problem with more complicated structures with internal pointers to other
35
-structures - these are NOT deallocated automaticaly because this function can't
36
-know the internal data structure and they must be freed by the
37
-caller!
35
+structures - for these you can set destroy function using
36
+<function>set_data_destroy_function</function>.
38 37
 <!-- detailed description -->
39 38
 </para>
40 39
 
41
-<para>This function does NOT free messages which were initialized using
42
-<function>message_init_ex</function> with <parameter>auto_free</parameter> not
43
-set, they must be freed explicitly by caller!
44
-</para>
45
-
46 40
 </refsect1>
47 41
 
48 42
 <refsect1><title>See Also</title>
49 43
 <para>
50 44
 <xref linkend="create_message"/>, <xref linkend="create_message_ex"/>, <xref
51
-linkend="init_message_ex"/>
45
+linkend="init_message_ex"/>, <xref linkend="set_data_destroy_function"/>
52 46
 <!-- references to other pages -->
53 47
 </para>
54 48
 </refsect1>
... ...
@@ -24,18 +24,20 @@
24 24
   <paramdef>mq_message_t *<parameter>m</parameter></paramdef>
25 25
   <paramdef>void *<parameter>data</parameter></paramdef>
26 26
   <paramdef>int <parameter>data_len</parameter></paramdef>
27
-  <paramdef>int <parameter>auto_free</parameter></paramdef>
27
+  <paramdef>destroy_function_f <parameter>func</parameter></paramdef>
28 28
 </funcprototype>
29 29
 
30 30
 </funcsynopsis></refsynopsisdiv>
31 31
 
32 32
 <refsect1><title>Description</title>
33
-<para>Initializes message structure with given data and given data length. If
34
-<parameter>auto_free</parameter> is set, the message can be be freed
35
-using <function>free_message</function> and such unremoved messages are freed
36
-automaticaly with <function>msg_queue_destroy</function>. If this flag is not set,
37
-calling <function>free message</function> will not do anything and the message
38
-and message data must be freed explicitly by caller.
33
+<para>Initializes message structure with given data and given data length like
34
+<function>create_message</function> but without its allocation. </para>
35
+<para>
36
+Parameter <parameter>func</parameter> specifies function called on data pointer
37
+before freeing the message in <function>free_message</function>. It can be NULL.
38
+This function may be used for example for memory deallocation (for example may
39
+have value of <function>cds_free_ptr</function>) or some more complicated
40
+function for freeing complex data structure with pointers inside or so.
39 41
 <!-- detailed description -->
40 42
 </para>
41 43
 
... ...
@@ -9,11 +9,19 @@
9 9
 <partintro>
10 10
 <para>Memory operations are common for whole CDS library. Because it must work
11 11
 together with SER's memory management and must work without it too, there are
12
+wrapper macros for memory allocation/deallocation.</para>
13
+
14
+<para>These macros were functions and it may change in the future, but macros
15
+are probably better - they allow better debuging than functions. There are
16
+defined another macros (see <xref linkend="cds_malloc_ptr"/>, <xref
17
+linkend="cds_free_ptr"/>), which point and will point to allocation/deallocation
18
+functions, thus they may be used as function pointers.
19
+<!--
12 20
 standalone functions (?macros in the future?) which cover internal
13
-implementation of memory allocation/deallocation functions.
21
+implementation of memory allocation/deallocation functions.-->
14 22
 </para>
15 23
 
16
-<para>It is possible to redefine these functions to help with memory debugging
24
+<para>It is possible to redefine these macros/functions to help with memory debugging
17 25
 or for monitoring purposes or so.
18 26
 </para>
19 27
 
... ...
@@ -26,4 +34,6 @@ with a memory debugging tool like valgrind
26 26
 <include xmlns="http://www.w3.org/2001/XInclude" href="cds_malloc.xml"/>
27 27
 <include xmlns="http://www.w3.org/2001/XInclude" href="cds_free.xml"/>
28 28
 
29
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_malloc_ptr.xml"/>
30
+<include xmlns="http://www.w3.org/2001/XInclude" href="cds_free_ptr.xml"/>
29 31
 </reference>
... ...
@@ -19,6 +19,7 @@ typedef struct _mq_message_t {
19 19
 	void *data;
20 20
 	int data_len;
21 21
 	struct _mq_message_t *next;
22
+	destroy_function_f destroy_function;
22 23
 	enum { 
23 24
 		message_allocated_with_data, 
24 25
 		message_holding_data_ptr 
... ...
@@ -45,14 +46,9 @@ message data should be obtained by <function>get_message_data</function>.
45 45
 	it after structure allocation, see <xref linkend="create_message_ex"/></para></listitem>
46 46
 
47 47
 	<listitem><para>there is third possibility, that data and message - both -
48
-	are allocated/freed by caller without using
48
+	are allocated by caller without using
49 49
 	<function>create_message</function>, <function>create_message_ex</function> and 
50 50
 	<function>msg_free</function>, see <xref linkend="init_message_ex"/></para>
51
-<!--	<para>In this case might be the <structname>mq_message_t</structname> for
52
-	example a part of the data structure.</para>
53
-	<para>This is not recomended because of
54
-	future possibility of <quote>network message queues</quote> and the
55
-	framework between could not free message memory.</para>-->
56 51
 	</listitem>
57 52
 </itemizedlist>
58 53
 </para>
... ...
@@ -30,6 +30,7 @@
30 30
 <include xmlns="http://www.w3.org/2001/XInclude" href="create_message.xml"/>
31 31
 <include xmlns="http://www.w3.org/2001/XInclude" href="create_message_ex.xml"/>
32 32
 <include xmlns="http://www.w3.org/2001/XInclude" href="init_message_ex.xml"/>
33
+<include xmlns="http://www.w3.org/2001/XInclude" href="set_data_destroy_function.xml"/>
33 34
 <include xmlns="http://www.w3.org/2001/XInclude" href="free_message.xml"/>
34 35
 
35 36
 </reference>
... ...
@@ -33,9 +33,8 @@ manipulation functions except <function>msg_queue_init</function>.
33 33
 <!-- detailed description -->
34 34
 </para>
35 35
 
36
-<para>All messages which stay in the queue and have <parameter>auto_free</parameter> flag set 
36
+<para>All messages which stay in the queue  
37 37
 are automaticaly freed using <function>free_message</function>. 
38
-It depends on allocation manner of messages if it is sufficient.
39 38
 </para>
40 39
 
41 40
 </refsect1>
42 41
new file mode 100644
... ...
@@ -0,0 +1,71 @@
0
+<?xml version="1.0" encoding="UTF-8"?>
1
+
2
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
3
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
4
+
5
+<refentry id="set_data_destroy_function"> <!-- ID for references -->
6
+
7
+<refmeta>
8
+<refentrytitle>set_data_destroy_function</refentrytitle> <!-- title shown in references -->
9
+<manvolnum>3</manvolnum></refmeta> <!-- man volume id (3 for libraries) -->
10
+
11
+<refnamediv>
12
+<refname>set_data_destroy_function</refname> <!-- function name -->
13
+<refpurpose>set function used to deallocate message data</refpurpose> <!-- short function description -->
14
+</refnamediv>
15
+
16
+<refsynopsisdiv><funcsynopsis>
17
+<funcsynopsisinfo>
18
+#include &lt;cds/msg_queue.h&gt; <!-- included headers -->
19
+
20
+typedef void (*destroy_function_f)(void *);
21
+</funcsynopsisinfo>
22
+
23
+<funcprototype> <!-- function prototype -->
24
+  <funcdef>void <function>set_data_destroy_function</function></funcdef>
25
+  <paramdef>mq_message_t *<parameter>msg</parameter></paramdef>
26
+  <paramdef>destroy_function_f <parameter>func</parameter></paramdef>
27
+</funcprototype>
28
+
29
+</funcsynopsis></refsynopsisdiv>
30
+
31
+<refsect1><title>Description</title>
32
+<para>Set destroy function for message data. This function is called from
33
+<function>free_message</function> and is primarily used for deallocation of
34
+complex data structures or their content. It can be used on all types of
35
+messages (allocated using <function>create_message</function> or
36
+<function>create_message_ex</function> or initialized using
37
+<function>init_message_ex</function>).
38
+<!-- detailed description -->
39
+</para>
40
+
41
+<example><title>Usage with create_message_ex</title>
42
+<programlisting>
43
+str_t *s;
44
+mq_message_t *msg = create_message_ex(sizeof(str_t));
45
+set_data_destroy_function((destroy_function_f)str_free_content);
46
+s = (str_t*)get_message_data(msg);
47
+str_dup_zt(s, "something happened");
48
+</programlisting>
49
+</example>
50
+
51
+<example><title>Usage with create_message</title>
52
+<programlisting>
53
+str_t *s = cds_malloc(sizeof(str_t));
54
+mq_message_t *msg = create_message(s, sizeof(str_t));
55
+set_data_destroy_function((destroy_function_f)str_free);
56
+str_dup_zt(s, "something happened");
57
+</programlisting>
58
+</example>
59
+
60
+</refsect1>
61
+
62
+<refsect1><title>See Also</title>
63
+<para><xref linkend="create_message"/>, <xref linkend="create_message_ex"/>,
64
+<xref linkend="init_message_ex"/>
65
+<!-- references to other pages -->
66
+</para>
67
+</refsect1>
68
+
69
+</refentry> 
70
+
... ...
@@ -24,6 +24,7 @@
24 24
  */
25 25
 
26 26
 #include <cds/hash_table.h>
27
+#include <cds/memory.h>
27 28
 #include <stdio.h>
28 29
 #include <stdlib.h>
29 30
 #include <string.h>
... ...
@@ -33,7 +34,7 @@ int ht_init(hash_table_t *ht, hash_func_t hash_func, key_cmp_func_t cmp_keys, in
33 33
 	if (!ht) return -1;
34 34
 	if ((!hash_func) || (!cmp_keys)) return -1;
35 35
 
36
-	ht->cslots = (ht_cslot_t*)malloc(size * sizeof(ht_cslot_t));
36
+	ht->cslots = (ht_cslot_t*)cds_malloc(size * sizeof(ht_cslot_t));
37 37
 	if (!ht->cslots) return -1;
38 38
 	memset(ht->cslots, 0, size * sizeof(ht_cslot_t));
39 39
 
... ...
@@ -59,11 +60,11 @@ void ht_destroy(hash_table_t *ht)
59 59
 			e = ht->cslots[i].first;
60 60
 			while (e) {
61 61
 				n = e->next;
62
-				free(e);
62
+				cds_free(e);
63 63
 				e = n;
64 64
 			}
65 65
 		}
66
-		free(ht->cslots);
66
+		cds_free(ht->cslots);
67 67
 	}
68 68
 	ht->cslots = NULL;
69 69
 }
... ...
@@ -74,7 +75,7 @@ int ht_add(hash_table_t *ht, ht_key_t key, ht_data_t data)
74 74
 	ht_element_t *new_e;
75 75
 	
76 76
 	if (!ht) return -1;
77
-	new_e = (ht_element_t*)malloc(sizeof(ht_element_t));
77
+	new_e = (ht_element_t*)cds_malloc(sizeof(ht_element_t));
78 78
 	if (!new_e) return -1;
79 79
 	new_e->next = NULL;
80 80
 	new_e->key = key;
... ...
@@ -136,7 +137,7 @@ ht_data_t ht_remove(hash_table_t *ht, ht_key_t key)
136 136
 			ht->cslots[h].cnt--;
137 137
 			if (!e->next) ht->cslots[h].last = p;
138 138
 			data = e->data;
139
-			free(e);
139
+			cds_free(e);
140 140
 			return data;
141 141
 		}
142 142
 		p = e;
... ...
@@ -29,137 +29,97 @@
29 29
 #include <stdio.h>
30 30
 #include <stdlib.h>
31 31
 #include <cds/memory.h>
32
+#include <cds/sync.h>
33
+#include <cds/logger.h>
32 34
 
33
-#ifdef SER
34
-
35
-#include <mem/mem.h>
36
-#include <mem/shm_mem.h>
37
-
38
-static void* shm_malloc_x(unsigned int size);
39
-static void shm_free_x(void *ptr);
35
+#ifdef TRACE_CDS_MEMORY
40 36
 
41
-cds_malloc_func cds_malloc = shm_malloc_x;
42
-cds_free_func cds_free = shm_free_x;
37
+cds_mutex_t *mem_mutex = NULL;
38
+int *allocated_cnt = NULL;
39
+char *debug_file = "/tmp/mem.log";
40
+
41
+#define write_debug(s,args...)	if (1) { \
42
+	FILE *f = fopen(debug_file, "a"); \
43
+	if (f) { \
44
+		fprintf(f,s,##args); \
45
+		fclose(f); \
46
+	} \
47
+	TRACE_LOG(s,##args); \
48
+}
43 49
 
50
+void *debug_malloc(int size, const char *file, int line)
51
+{
52
+	void *m = NULL;
53
+	if (allocated_cnt && mem_mutex) {
54
+		cds_mutex_lock(mem_mutex);
55
+		(*allocated_cnt)++;
56
+		cds_mutex_unlock(mem_mutex);
57
+	}
58
+#ifdef SER
59
+	m = shm_malloc(size);
44 60
 #else
45
-
46
-cds_malloc_func cds_malloc = malloc;
47
-cds_free_func cds_free = free;
48
-
61
+	m = malloc(size);
49 62
 #endif
50
-
51
-void cds_set_memory_functions(cds_malloc_func _malloc, cds_free_func _free)
52
-{
53
-	cds_malloc = _malloc;
54
-	cds_free = _free;
63
+	write_debug("ALLOC %p size %u from %s(%d)\n", m, size, file, line);
64
+	/* LOG(L_INFO, "debug_malloc(): %p\n", m); */
65
+	return m;
55 66
 }
56 67
 
68
+void debug_free(void *block, const char *file, int line)
69
+{
70
+	if (allocated_cnt && mem_mutex) {
71
+		cds_mutex_lock(mem_mutex);
72
+		(*allocated_cnt)--;
73
+		cds_mutex_unlock(mem_mutex);
74
+	}
57 75
 #ifdef SER
76
+	shm_free(block);
77
+#else
78
+	free(block);
79
+#endif
80
+	write_debug("FREE %p from %s(%d)\n", block, file, line);
81
+}
58 82
 
59
-static void* shm_malloc_x(unsigned int size)
83
+void *debug_malloc_ex(unsigned int size)
60 84
 {
61
-	return shm_malloc(size);
85
+	return debug_malloc(size, "<none>", 0);
62 86
 }
63 87
 
64
-static void shm_free_x(void *ptr)
88
+void debug_free_ex(void *block)
65 89
 {
66
-	shm_free(ptr);
90
+	debug_free(block, "<none>", 0);
67 91
 }
68 92
 
69
-#endif
70
-
71
-/*
72
-#ifdef SER
73
-
74
-static gen_lock_t *mem_mutex = NULL;
75
-int *allocated_cnt = NULL;
76
-
77
-#else
78
-
79
-static int allocated_cnt = 0;
80
-
81
-#endif
82
-
83
-void debug_mem_init()
93
+void cds_memory_trace_init()
84 94
 {
85
-#ifdef SER
86
-	mem_mutex = lock_alloc();
87
-	allocated_cnt = shm_malloc(sizeof(int));
95
+	cds_mutex_init(mem_mutex);
96
+	allocated_cnt = cds_malloc(sizeof(int));
88 97
 	*allocated_cnt = 0;
89
-	debug_print_allocated_mem();
90
-#else
91
-	allocated_cnt = 0;
92
-#endif
93 98
 }
94 99
 
95
-void *debug_malloc(int size)
100
+void cds_memory_trace(char *dst, int dst_len)
96 101
 {
97
-#ifdef SER
98
-	void *m = NULL;
99
-	lock_get(mem_mutex);
100
-	if (allocated_cnt) (*allocated_cnt)++;
101
-	lock_release(mem_mutex);
102
-	m = shm_malloc(size);
103
-	LOG(L_INFO, "debug_malloc(): %p\n", m);
104
-	return m;
105
-#else
106
-	allocated_cnt++;
107
-	return malloc(size);
108
-#endif
102
+	if (allocated_cnt && mem_mutex) {
103
+		cds_mutex_lock(mem_mutex);
104
+		snprintf(dst, dst_len, "There are allocated: %d memory blocks\n", *allocated_cnt);
105
+		cds_mutex_unlock(mem_mutex);
106
+	}
109 107
 }
110 108
 
111
-void debug_free(void *block)
112
-{
109
+#else /* ! CDS_TRACE_MEMORY */
110
+
113 111
 #ifdef SER
114
-	LOG(L_INFO, "debug_free(): %p\n", block);
115
-	shm_free(block);
116
-	lock_get(mem_mutex);
117
-	if (allocated_cnt) (*allocated_cnt)--;
118
-	lock_release(mem_mutex);
119
-#else
120
-	free(block);
121
-	allocated_cnt--;
122
-#endif
123
-}
124 112
 
125
-void *debug_malloc_ex(int size, const char *file, int line)
113
+void* shm_malloc_x(unsigned int size)
126 114
 {
127
-#ifdef SER
128
-	void *m = NULL;
129
-	lock_get(mem_mutex);
130
-	if (allocated_cnt) (*allocated_cnt)++;
131
-	lock_release(mem_mutex);
132
-	m = shm_malloc(size);
133
-	LOG(L_INFO, "ALLOC: %s:%d -> %p\n", file, line, m);
134
-	return m;
135
-#else
136
-	allocated_cnt++;
137
-	return malloc(size);
138
-#endif
115
+	return shm_malloc(size);
139 116
 }
140 117
 
141
-void debug_free_ex(void *block, const char *file, int line)
118
+void shm_free_x(void *ptr)
142 119
 {
143
-#ifdef SER
144
-	LOG(L_INFO, "FREE: %s:%d -> %p\n", file, line, block);
145
-	shm_free(block);
146
-	lock_get(mem_mutex);
147
-	if (allocated_cnt) (*allocated_cnt)--;
148
-	lock_release(mem_mutex);
149
-#else
150
-	free(block);
151
-	allocated_cnt--;
152
-#endif
120
+	shm_free(ptr);
153 121
 }
154 122
 
155
-void debug_print_allocated_mem()
156
-{
157
-#ifdef SER
158
-	lock_get(mem_mutex);
159
-	LOG(L_INFO, "There are allocated: %d memory blocks\n", *allocated_cnt);
160
-	lock_release(mem_mutex);
161
-#else
162
-	printf("There are allocated: %d memory blocks\n", allocated_cnt);
163 123
 #endif
164
-}
165
-*/
124
+
125
+#endif
... ...
@@ -26,17 +26,64 @@
26 26
 #ifndef __CDS_MEMORY_H
27 27
 #define __CDS_MEMORY_H
28 28
 
29
+/* #define TRACE_CDS_MEMORY */
30
+
29 31
 #ifdef __cplusplus
30 32
 extern "C" {
31 33
 #endif
32 34
 
33
-typedef void*(*cds_malloc_func)(unsigned int size);
35
+/* typedef void*(*cds_malloc_func)(unsigned int size);
34 36
 typedef void(*cds_free_func)(void *ptr);
35 37
 
36 38
 extern cds_malloc_func cds_malloc;
37 39
 extern cds_free_func cds_free;
38 40
 
39
-void cds_set_memory_functions(cds_malloc_func _malloc, cds_free_func _free);
41
+void cds_set_memory_functions(cds_malloc_func _malloc, cds_free_func _free); */
42
+
43
+#ifdef TRACE_CDS_MEMORY
44
+
45
+void *debug_malloc(int size, const char *file, int line);
46
+void debug_free(void *block, const char *file, int line);
47
+void *debug_malloc_ex(unsigned int size);
48
+void debug_free_ex(void *block);
49
+
50
+/* trace function */
51
+void cds_memory_trace(char *dst, int dst_len);
52
+/* initializes internal variables for memory tracing */
53
+void cds_memory_trace_init();
54
+
55
+#define cds_malloc(s)	debug_malloc(s,__FILE__, __LINE__)
56
+#define cds_free(p)		debug_free(p,__FILE__, __LINE__)
57
+#define cds_free_ptr	debug_free_ex
58
+#define cds_malloc_ptr	debug_malloc_ex
59
+
60
+#else /* !TRACE */
61
+
62
+#ifdef SER
63
+
64
+#include <mem/mem.h>
65
+#include <mem/shm_mem.h>
66
+
67
+void* shm_malloc_x(unsigned int size);
68
+void shm_free_x(void *ptr);
69
+
70
+#define cds_malloc(s)	shm_malloc(s)
71
+#define cds_free(p)		shm_free(p)
72
+#define cds_malloc_ptr	shm_malloc_x
73
+#define cds_free_ptr	shm_free_x
74
+
75
+#else /* !SER */
76
+
77
+#include <stdlib.h>
78
+
79
+#define cds_malloc(s)	malloc(s)
80
+#define cds_free(p)		free(p)
81
+#define cds_malloc_ptr	malloc
82
+#define cds_free_ptr	free
83
+
84
+#endif /* !SER */
85
+
86
+#endif /* !TRACE_CDS_MEMORY */
40 87
 
41 88
 #ifdef __cplusplus
42 89
 }
... ...
@@ -37,6 +37,7 @@ mq_message_t *create_message_ex(int data_len)
37 37
 	m->data = (((char *)m) + sizeof(mq_message_t));
38 38
 	m->next = NULL;
39 39
 	m->allocation_style = message_allocated_with_data;
40
+	m->destroy_function = NULL;
40 41
 	return m;
41 42
 }
42 43
 
... ...
@@ -50,10 +51,11 @@ mq_message_t *create_message(void *data, int data_len)
50 50
 	m->data = data;
51 51
 	m->next = NULL;
52 52
 	m->allocation_style = message_holding_data_ptr;
53
+	m->destroy_function = cds_free_ptr;
53 54
 	return m;
54 55
 }
55 56
 
56
-void init_message_ex(mq_message_t *m, void *data, int data_len, int auto_free)
57
+void init_message_ex(mq_message_t *m, void *data, int data_len, destroy_function_f func)
57 58
 {
58 59
 	/* if (data_len < 0) data_len = 0; */
59 60
 	if (!m) return;
... ...
@@ -61,21 +63,25 @@ void init_message_ex(mq_message_t *m, void *data, int data_len, int auto_free)
61 61
 	m->data_len = data_len;
62 62
 	m->data = data;
63 63
 	m->next = NULL;
64
-	if (auto_free) m->allocation_style = message_holding_data_ptr;
65
-	else m->allocation_style = message_holding_data_ptr_no_free;
64
+	m->destroy_function = func;
65
+	m->allocation_style = message_holding_data_ptr;
66
+}
67
+
68
+void set_data_destroy_function(mq_message_t *msg, destroy_function_f func)
69
+{
70
+	if (msg) msg->destroy_function = func;
66 71
 }
67 72
 
68 73
 void free_message(mq_message_t *msg)
69 74
 {
75
+	if (msg->destroy_function && msg->data) 
76
+		msg->destroy_function(msg->data);
70 77
 	switch (msg->allocation_style) {
71 78
 		case message_allocated_with_data: 
72 79
 				break;
73 80
 		case message_holding_data_ptr: 
74
-				if (msg->data) cds_free(msg->data);
81
+				/* if (msg->data) cds_free(msg->data); */
75 82
 				break;
76
-		case message_holding_data_ptr_no_free:
77
-				/* not automaticaly freed !! */
78
-				return;
79 83
 	}
80 84
 	cds_free(msg);
81 85
 }
... ...
@@ -28,14 +28,16 @@
28 28
 
29 29
 #include <cds/sync.h>
30 30
 
31
+typedef void (*destroy_function_f)(void *);
32
+
31 33
 typedef struct _mq_message_t {
32 34
 	void *data;
33 35
 	int data_len;
34 36
 	struct _mq_message_t *next;
37
+	destroy_function_f destroy_function; /* see doc */
35 38
 	enum { 
36 39
 		message_allocated_with_data, 
37
-		message_holding_data_ptr, 
38
-		message_holding_data_ptr_no_free /* not automaticaly freed */
40
+		message_holding_data_ptr
39 41
 	} allocation_style;
40 42
 	char data_buf[1];
41 43
 } mq_message_t;
... ...
@@ -59,10 +61,12 @@ mq_message_t *create_message_ex(int data_len);
59 59
  * are automacicaly freed! */
60 60
 mq_message_t *create_message(void *data, int data_len);
61 61
 
62
+void set_data_destroy_function(mq_message_t *msg, destroy_function_f func);
63
+
62 64
 /** initializes message, 
63 65
  * if auto_free set, data must be allocated using cds_malloc and are automaticaly freed by free_message 
64 66
  * (and if msg_queue_destroy called) */
65
-void init_message_ex(mq_message_t *m, void *data, int data_len, int auto_free);
67
+void init_message_ex(mq_message_t *m, void *data, int data_len, destroy_function_f func);
66 68
 
67 69
 /** frees the message and data holding by the message !!!! */
68 70
 void free_message(mq_message_t *msg);
... ...
@@ -163,13 +163,13 @@ int str_case_equals(const str_t *a, const str_t *b)
163 163
 	return 0;
164 164
 }
165 165
 
166
-void str_free_content(str_t *s)
166
+/* void str_free_content(str_t *s)
167 167
 {
168 168
 	if (!s) return;
169 169
 	if ((s->len > 0) && (s->s)) cds_free(s->s);
170 170
 	s->len = 0;
171 171
 	s->s = NULL;
172
-}
172
+} 
173 173
 
174 174
 void str_free(str_t *s)
175 175
 {
... ...
@@ -177,7 +177,7 @@ void str_free(str_t *s)
177 177
 		str_free_content(s);
178 178
 		cds_free(s);
179 179
 	}
180
-}
180
+}*/
181 181
 
182 182
 void str_clear(str_t *s)
183 183
 {
... ...
@@ -26,6 +26,8 @@
26 26
 #ifndef __SIMPLE_STR_H
27 27
 #define __SIMPLE_STR_H
28 28
 
29
+#include <cds/memory.h>
30
+
29 31
 #ifdef __cplusplus
30 32
 extern "C" {
31 33
 #endif
... ...
@@ -66,10 +68,19 @@ int str_dup_zt(str_t* dst, const char* src);
66 66
 char *zt_strdup(const char*src);
67 67
 
68 68
 /** frees string content if allocated */
69
-void str_free_content(str_t *s);
69
+/* void str_free_content(str_t *s); */
70
+#define str_free_content(str)	if (str) { \
71
+		if (((str)->len > 0) && ((str)->s)) cds_free((str)->s);\
72
+		(str)->len = 0; \
73
+		(str)->s = 0; \
74
+	}
70 75
 
71 76
 /** frees string content if allocated and then the string itself */
72
-void str_free(str_t *s);
77
+/* void str_free(str_t *s); */
78
+#define str_free(str)	if (str) { \
79
+		str_free_content(str); \
80
+		cds_free(str); \
81
+	}
73 82
 
74 83
 /** case sensitive comparation - returns 0 if equal, nonzero otherwise */
75 84
 int str_case_equals(const str_t *a, const str_t *b);
... ...
@@ -18,21 +18,6 @@
18 18
 representation and helper functions.
19 19
 </para>
20 20
 
21
-<section><title>Conventions</title>
22
-<para>There is list of conventions used in this library:
23
-<itemizedlist>
24
-	<listitem><para>data types (structures, enums, ...) have their names with suffix 
25
-	<quote>_t</quote> (<structname>dstring_t</structname>, 
26
-	<structname>str_t</structname>, ...)</para></listitem>
27
-	<listitem><para>many functions have prefix according to data structure on
28
-	which are operating (like <function>dstr_append</function> which operates on
29
-	<structname>dstring_t</structname> data structure)</para></listitem>
30
-	<listitem><para>most functions return 0 as successful result and nonzero
31
-	value as error</para></listitem>
32
-</itemizedlist>
33
-</para>
34
-</section>
35
-
36 21
 <section id="libpresence.dependencies"><title>Dependencies</title>
37 22
 <para>
38 23
 <itemizedlist>
... ...
@@ -249,6 +249,8 @@ void unregister_notifier(notifier_domain_t *domain, notifier_t *info)
249 249
 {
250 250
 	notifier_package_t *p;
251 251
 
252
+	if ((!info) || (!domain)) return;
253
+
252 254
 	/* maybe: test if the NOTIFIER is registered before unregistration */
253 255
 
254 256
 	lock_notifier_domain(domain);
... ...
@@ -17,21 +17,6 @@
17 17
 <para>This library contains functions for manipulating data using XCAP protocol.
18 18
 </para>
19 19
 
20
-<section><title>Conventions</title>
21
-<para>There is list of conventions used in this library:
22
-<itemizedlist>
23
-	<listitem><para>data types (structures, enums, ...) have their names with suffix 
24
-	<quote>_t</quote> (<structname>dstring_t</structname>, 
25
-	<structname>str_t</structname>, ...)</para></listitem>
26
-	<listitem><para>many functions have prefix according to data structure on
27
-	which are operating (like <function>dstr_append</function> which operates on
28
-	<structname>dstring_t</structname> data structure)</para></listitem>
29
-	<listitem><para>most functions return 0 as successful result and nonzero
30
-	value as error</para></listitem>
31
-</itemizedlist>
32
-</para>
33
-</section>
34
-
35 20
 <section id="libxcap.dependencies"><title>Dependencies</title>
36 21
 <para>
37 22
 <itemizedlist>
... ...
@@ -260,7 +260,7 @@ void free_service(service_t *s)
260 260
 
261 261
 	switch (s->content_type) {
262 262
 		case stc_list: free_list(s->content.list); break;
263
-		case stc_resource_list: free(s->content.resource_list); break;
263
+		case stc_resource_list: cds_free(s->content.resource_list); break;
264 264
 	}
265 265
 	
266 266
 	free_packages(s->packages);