GVariant: fix some refcounting issues
[platform/upstream/glib.git] / glib / gbuffer.c
1 /*
2  * Copyright © 2009, 2010 Codethink Limited
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the licence, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Author: Ryan Lortie <desrt@desrt.ca>
20  */
21
22 #include "config.h"
23
24 #include "gbuffer.h"
25
26 #include <glib/gstrfuncs.h>
27 #include <glib/gatomic.h>
28 #include <glib/gmem.h>
29
30 #include "galias.h"
31
32 typedef struct
33 {
34   GBuffer buffer;
35
36   GDestroyNotify user_destroy;
37   gpointer user_data;
38 } GUserNotifyBuffer;
39
40 static void
41 g_buffer_free_gfree (GBuffer *buffer)
42 {
43   g_free ((gpointer) buffer->data);
44   g_slice_free (GBuffer, buffer);
45 }
46
47 /* < private >
48  * g_buffer_new_from_data:
49  * @data: the data to be used for the buffer
50  * @size: the size of @data
51  * @returns: a reference to a new #GBuffer
52  *
53  * Creates a new #GBuffer from @data.
54  *
55  * @data is copied.
56  */
57
58 GBuffer *
59 g_buffer_new_from_data (gconstpointer data,
60                         gsize         size)
61 {
62   GBuffer *buffer;
63
64   buffer = g_slice_new (GBuffer);
65   buffer->data = g_memdup (data, size);
66   buffer->size = size;
67   buffer->free_func = g_buffer_free_gfree;
68   buffer->ref_count = 1;
69
70   return buffer;
71 }
72
73 /* < private >
74  * g_buffer_new_take_data:
75  * @data: the data to be used for the buffer
76  * @size: the size of @data
77  * returns: a reference to a new #GBuffer
78  *
79  * Creates a new #GBuffer from @data.
80  *
81  * @data must have been created by a call to g_malloc(), g_malloc0() or
82  * g_realloc() or by one of the many functions that wrap these calls
83  * (such as g_new(), g_strdup(), etc).
84  *
85  * After this call, @data belongs to the buffer and may no longer be
86  * modified by the caller.  g_free() will be called on @data when the
87  * buffer is no longer in use.
88  */
89 GBuffer *
90 g_buffer_new_take_data (gpointer data,
91                         gsize    size)
92 {
93   GBuffer *buffer;
94
95   buffer = g_slice_new (GBuffer);
96   buffer->data = data;
97   buffer->size = size;
98   buffer->free_func = g_buffer_free_gfree;
99   buffer->ref_count = 1;
100
101   return buffer;
102 }
103
104 static void
105 g_buffer_free (GBuffer *buffer)
106 {
107   g_slice_free (GBuffer, buffer);
108 }
109
110 /* < private >
111  * g_buffer_new_from_static_data:
112  * @data: the data to be used for the buffer
113  * @size: the size of @data
114  * @returns: a reference to a new #GBuffer
115  *
116  * Creates a new #GBuffer from static data.
117  *
118  * @data must be static (ie: never modified or freed).
119  */
120 GBuffer *
121 g_buffer_new_from_static_data (gconstpointer data,
122                                gsize         size)
123 {
124   GBuffer *buffer;
125
126   buffer = g_slice_new (GBuffer);
127   buffer->data = data;
128   buffer->size = size;
129   buffer->free_func = g_buffer_free;
130   buffer->ref_count = 1;
131
132   return buffer;
133 }
134
135 static void
136 g_buffer_free_usernotify (GBuffer *buffer)
137 {
138   GUserNotifyBuffer *ubuffer = (GUserNotifyBuffer *) buffer;
139
140   ubuffer->user_destroy (ubuffer->user_data);
141   g_slice_free (GBuffer, buffer);
142 }
143
144 /* < private >
145  * g_buffer_new_from_pointer:
146  * @data: the data to be used for the buffer
147  * @size: the size of @data
148  * @notify: the function to call to release the data
149  * @user_data: the data to pass to @notify
150  * @returns: a reference to a new #GBuffer
151  *
152  * Creates a #GBuffer from @data.
153  *
154  * When the last reference is dropped, @notify will be called on
155  * @user_data.
156  *
157  * @data must not be modified after this call is made, until @notify has
158  * been called to indicate that the buffer is no longer in use.
159  */
160 GBuffer *
161 g_buffer_new_from_pointer (gconstpointer  data,
162                            gsize          size,
163                            GDestroyNotify notify,
164                            gpointer       user_data)
165 {
166   GUserNotifyBuffer *ubuffer;
167
168   ubuffer = g_slice_new (GUserNotifyBuffer);
169   ubuffer->buffer.data = data;
170   ubuffer->buffer.size = size;
171   ubuffer->buffer.free_func = g_buffer_free_usernotify;
172   ubuffer->buffer.ref_count = 1;
173   ubuffer->user_destroy = notify;
174   ubuffer->user_data = user_data;
175
176   return (GBuffer *) ubuffer;
177 }
178
179 /* < private >
180  * g_buffer_ref:
181  * @buffer: a #GBuffer
182  * @returns: @buffer
183  *
184  * Increase the reference count on @buffer.
185  */
186 GBuffer *
187 g_buffer_ref (GBuffer *buffer)
188 {
189   g_atomic_int_inc (&buffer->ref_count);
190
191   return buffer;
192 }
193
194 /* < private >
195  * g_buffer_unref:
196  * @buffer: a #GBuffer
197  *
198  * Releases a reference on @buffer.  This may result in the buffer being
199  * freed.
200  */
201 void
202 g_buffer_unref (GBuffer *buffer)
203 {
204   if (g_atomic_int_dec_and_test (&buffer->ref_count))
205     if (buffer->free_func != NULL)
206       buffer->free_func (buffer);
207 }