First THREADED backport attempt, focusing on adding locks and making sure the API...
[platform/upstream/gstreamer.git] / gst / gstdata.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wim@fluendo.com>
4  *
5  * gstdata.c: Data operations
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include "gst_private.h"
24
25 #include "gstatomic_impl.h"
26 #include "gstdata.h"
27 #include "gstdata_private.h"
28 #include "gstinfo.h"
29
30 GType
31 gst_data_get_type (void)
32 {
33   static GType type = 0;
34
35   if (!type)
36     type = g_boxed_type_register_static ("GstData",
37         (GBoxedCopyFunc) gst_data_copy, (GBoxedFreeFunc) gst_data_unref);
38   return type;
39 }
40
41 /**
42  * gst_data_init:
43  * @data: a #GstData to initialize
44  * @type: the type of this data
45  * @flags: flags for this data
46  * @free: a free function
47  * @copy: a copy function
48  *
49  * Initialize the given data structure with the given parameters.
50  * The free and copy function will be called when this data is freed
51  * or copied, respectively.
52  */
53 void
54 gst_data_init (GstData * data, GType type, guint16 flags,
55     GstDataFreeFunction free, GstDataCopyFunction copy)
56 {
57   g_return_if_fail (data != NULL);
58
59   _GST_DATA_INIT (data, type, flags, free, copy);
60 }
61
62 /**
63  * gst_data_copy_into:
64  * @data: a #GstData to copy
65  * @target: the target #GstData to copy into
66  *
67  * Copy the GstData into the specified target GstData structure.
68  * This method is mainly used by subclasses when they want to copy
69  * the relevant GstData info.
70  */
71 void
72 gst_data_copy_into (const GstData * data, GstData * target)
73 {
74   g_return_if_fail (data != NULL);
75 }
76
77 /**
78  * gst_data_dispose:
79  * @data: a #GstData to dispose
80  *
81  * Free all the resources allocated in the gst_data_init() function,
82  * mainly used by subclass implementors.
83  */
84 void
85 gst_data_dispose (GstData * data)
86 {
87   g_return_if_fail (data != NULL);
88
89   _GST_DATA_DISPOSE (data);
90 }
91
92 /**
93  * gst_data_copy:
94  * @data: a #GstData to copy
95  *
96  * Copies the given #GstData. This function will call the custom subclass
97  * copy function or return NULL if no function was provided by the subclass.
98  *
99  * Returns: a copy of the data or NULL if the data cannot be copied.
100  * The refcount of the original buffer is not changed so you should unref it
101  * when you don't need it anymore.
102  *
103  * MT safe.
104  */
105 GstData *
106 gst_data_copy (const GstData * data)
107 {
108   g_return_val_if_fail (data != NULL, NULL);
109
110   if (data->copy)
111     return data->copy (data);
112
113   return NULL;
114 }
115
116 /**
117  * gst_data_is_writable:
118  * @data: a #GstData to check
119  *
120  * Query if the data needs to be copied before it can safely be modified.
121  *
122  * Returns: FALSE if the given #GstData is potentially shared and needs to
123  * be copied before it can be modified safely.
124  *
125  * MT safe.
126  */
127 gboolean
128 gst_data_is_writable (GstData * data)
129 {
130   gint refcount;
131
132   g_return_val_if_fail (data != NULL, FALSE);
133
134   refcount = gst_atomic_int_read (&data->refcount);
135
136   /* if we have the only ref and the data is not readonly, we can
137    * safely write */
138   if (refcount == 1 && !GST_DATA_FLAG_IS_SET (data, GST_DATA_READONLY))
139     return TRUE;
140
141   return FALSE;
142 }
143
144 /**
145  * gst_data_copy_on_write:
146  * @data: a #GstData to copy
147  *
148  * Copies the given #GstData if the refcount is greater than 1 so that the
149  * #GstData object can be written to safely.
150  *
151  * Returns: a copy of the data if the refcount is > 1 or the buffer is
152  * marked READONLY, data if the refcount == 1,
153  * or NULL if the data could not be copied.
154  *
155  * The refcount of the passed @data is decreased when a copy is made, so
156  * you are not supposed to use it anymore after a call to this function.
157  *
158  * MT safe.
159  */
160 GstData *
161 gst_data_copy_on_write (GstData * data)
162 {
163   gint refcount;
164
165   g_return_val_if_fail (data != NULL, NULL);
166
167   refcount = gst_atomic_int_read (&data->refcount);
168
169   /* if we have the only ref and the data is not readonly, we can
170    * safely write, so we return the input data */
171   if (refcount == 1 && !GST_DATA_FLAG_IS_SET (data, GST_DATA_READONLY))
172     return GST_DATA (data);
173
174   if (data->copy) {
175     GstData *copy = data->copy (data);
176
177     gst_data_unref (data);
178     return copy;
179   }
180
181   return NULL;
182 }
183
184 /**
185  * gst_data_ref:
186  * @data: a #GstData to reference
187  *
188  * Increments the reference count of this data.
189  *
190  * Returns: the data
191  *
192  * MT safe.
193  */
194 GstData *
195 gst_data_ref (GstData * data)
196 {
197   g_return_val_if_fail (data != NULL, NULL);
198   g_return_val_if_fail (GST_DATA_REFCOUNT_VALUE (data) > 0, NULL);
199
200   GST_CAT_LOG (GST_CAT_BUFFER, "%p %d->%d", data,
201       GST_DATA_REFCOUNT_VALUE (data), GST_DATA_REFCOUNT_VALUE (data) + 1);
202
203   gst_atomic_int_inc (&data->refcount);
204
205   return data;
206 }
207
208 /**
209  * gst_data_ref_by_count:
210  * @data: a #GstData to reference
211  * @count: the number to increment the reference count by
212  *
213  * Increments the reference count of this data by the given number.
214  *
215  * Returns: the data
216  *
217  * MT safe.
218  */
219 GstData *
220 gst_data_ref_by_count (GstData * data, gint count)
221 {
222   g_return_val_if_fail (data != NULL, NULL);
223   g_return_val_if_fail (count >= 0, NULL);
224   g_return_val_if_fail (GST_DATA_REFCOUNT_VALUE (data) > 0, NULL);
225
226   GST_CAT_LOG (GST_CAT_BUFFER, "%p %d->%d", data,
227       GST_DATA_REFCOUNT_VALUE (data), GST_DATA_REFCOUNT_VALUE (data) + count);
228
229   gst_atomic_int_add (&data->refcount, count);
230
231   return data;
232 }
233
234 /**
235  * gst_data_unref:
236  * @data: a #GstData to unreference
237  *
238  * Decrements the refcount of this data. If the refcount is
239  * zero, the data will be freed.
240  *
241  * When you move data out of your element into the pipeline,
242  * the pipeline takes ownership of the
243  * data.  When the data has been consumed by some element, it must unref() it.
244  * Applications usually don't need to unref() @data.
245  *
246  * MT safe.
247  */
248 void
249 gst_data_unref (GstData * data)
250 {
251   gint zero;
252
253   g_return_if_fail (data != NULL);
254
255   GST_CAT_LOG (GST_CAT_BUFFER, "%p %d->%d", data,
256       GST_DATA_REFCOUNT_VALUE (data), GST_DATA_REFCOUNT_VALUE (data) - 1);
257   g_return_if_fail (GST_DATA_REFCOUNT_VALUE (data) > 0);
258
259   zero = gst_atomic_int_dec_and_test (&data->refcount);
260
261   /* if we ended up with the refcount at zero, free the data */
262   if (zero) {
263     if (data->free)
264       data->free (data);
265   }
266 }