Add reference counting and boxed types for GArray, GByteArray and GPtrArray.
Signed-off-by: Matthias Clasen <mclasen@redhat.com>
GArray
g_array_new
g_array_sized_new
+g_array_ref
+g_array_unref
+g_array_get_element_size
g_array_append_val
g_array_append_vals
g_array_prepend_val
GPtrArray
g_ptr_array_new
g_ptr_array_sized_new
+g_ptr_array_new_with_free_func
+g_ptr_array_set_free_func
+g_ptr_array_ref
+g_ptr_array_unref
g_ptr_array_add
g_ptr_array_remove
g_ptr_array_remove_index
GByteArray
g_byte_array_new
g_byte_array_sized_new
+g_byte_array_ref
+g_byte_array_unref
g_byte_array_append
g_byte_array_prepend
g_byte_array_remove_index
<!-- ##### FUNCTION g_array_new ##### -->
<para>
-Creates a new #GArray.
+Creates a new #GArray with a reference count of 1.
</para>
@zero_terminated: %TRUE if the array should have an extra element at the end
<!-- ##### FUNCTION g_array_sized_new ##### -->
<para>
Creates a new #GArray with @reserved_size elements
-preallocated. This avoids frequent reallocation, if you are going to
-add many elements to the array. Note however that the size of the
-array is still 0.
+preallocated and a reference count of 1. This avoids frequent reallocation,
+if you are going to add many elements to the array. Note however that the
+size of the array is still 0.
</para>
@zero_terminated: %TRUE if the array should have an extra element at the end with all bits cleared.
@Returns: the new #GArray.
+<!-- ##### FUNCTION g_array_ref ##### -->
+<para>
+
+</para>
+
+@array:
+@Returns:
+
+
+<!-- ##### FUNCTION g_array_unref ##### -->
+<para>
+
+</para>
+
+@array:
+
+
+<!-- ##### FUNCTION g_array_get_element_size ##### -->
+<para>
+
+</para>
+
+@array:
+@Returns:
+
+
<!-- ##### MACRO g_array_append_val ##### -->
<para>
Adds the value on to the end of the array.
<para>
Frees the memory allocated for the #GArray.
If @free_segment is %TRUE it frees the memory block holding the elements
-as well. Pass %FALSE if you want to free the #GArray wrapper but preserve
-the underlying array for use elsewhere.
+as well and also each element if @array has a @element_free_func set.
+Pass %FALSE if you want to free the #GArray wrapper but preserve
+the underlying array for use elsewhere. If the reference count of @array
+is greater than one, the #GArray wrapper is preserved but the size of
+@array will be set to zero.
</para>
<note>
<para>
<!-- ##### FUNCTION g_byte_array_new ##### -->
<para>
-Creates a new #GByteArray.
+Creates a new #GByteArray with a reference count of 1.
</para>
@Returns: the new #GByteArray.
@Returns: the new #GByteArray.
+<!-- ##### FUNCTION g_byte_array_ref ##### -->
+<para>
+
+</para>
+
+@array:
+@Returns:
+
+
+<!-- ##### FUNCTION g_byte_array_unref ##### -->
+<para>
+
+</para>
+
+@array:
+
+
<!-- ##### FUNCTION g_byte_array_append ##### -->
<para>
Adds the given bytes to the end of the #GByteArray.
<!-- ##### FUNCTION g_byte_array_free ##### -->
<para>
Frees the memory allocated by the #GByteArray.
-If @free_segment is %TRUE it frees the actual byte data.
+If @free_segment is %TRUE it frees the actual byte data. If the reference
+count of @array is greater than one, the #GByteArray wrapper is preserved but
+the size of @array will be set to zero.
</para>
@array: a #GByteArray.
<!-- ##### FUNCTION g_ptr_array_new ##### -->
<para>
-Creates a new #GPtrArray.
+Creates a new #GPtrArray with a reference count of 1.
</para>
@Returns: the new #GPtrArray.
<!-- ##### FUNCTION g_ptr_array_sized_new ##### -->
<para>
Creates a new #GPtrArray with @reserved_size pointers
-preallocated. This avoids frequent reallocation, if you are going to
-add many pointers to the array. Note however that the size of the
-array is still 0.
+preallocated and a reference count of 1. This avoids frequent reallocation,
+if you are going to add many pointers to the array. Note however that the size
+of the array is still 0.
</para>
@reserved_size: number of pointers preallocated.
@Returns: the new #GPtrArray.
+<!-- ##### FUNCTION g_ptr_array_new_with_free_func ##### -->
+<para>
+
+</para>
+
+@element_free_func:
+@Returns:
+
+
+<!-- ##### FUNCTION g_ptr_array_set_free_func ##### -->
+<para>
+
+</para>
+
+@array:
+@element_free_func:
+
+
+<!-- ##### FUNCTION g_ptr_array_ref ##### -->
+<para>
+
+</para>
+
+@array:
+@Returns:
+
+
+<!-- ##### FUNCTION g_ptr_array_unref ##### -->
+<para>
+
+</para>
+
+@array:
+
+
<!-- ##### FUNCTION g_ptr_array_add ##### -->
<para>
Adds a pointer to the end of the pointer array.
<para>
Removes the first occurrence of the given pointer from the pointer array.
The following elements are moved down one place.
+If @array has a non-%NULL #GDestroyNotify function it is called for
+the removed element.
</para>
<para>
It returns %TRUE if the pointer was removed, or %FALSE if the pointer
<para>
Removes the pointer at the given index from the pointer array.
The following elements are moved down one place.
+If @array has a non-%NULL #GDestroyNotify function it is called for
+the removed element.
</para>
@array: a #GPtrArray.
The last element in the array is used to fill in the space, so this function
does not preserve the order of the array. But it is faster than
g_ptr_array_remove().
+If @array has a non-%NULL #GDestroyNotify function it is called for
+the removed element.
</para>
<para>
It returns %TRUE if the pointer was removed, or %FALSE if the pointer
The last element in the array is used to fill in the space, so this function
does not preserve the order of the array. But it is faster than
g_ptr_array_remove_index().
+If @array has a non-%NULL #GDestroyNotify function it is called for
+the removed element.
</para>
@array: a #GPtrArray.
<para>
Removes the given number of pointers starting at the given index from a
#GPtrArray. The following elements are moved to close the gap.
+If @array has a non-%NULL #GDestroyNotify function it is called for
+the removed elements.
</para>
@array: a @GPtrArray.
<!-- ##### FUNCTION g_ptr_array_free ##### -->
<para>
Frees the memory allocated for the #GPtrArray.
-If @free_segment is %TRUE it frees the memory block holding the elements
+If @free_seg is %TRUE it frees the memory block holding the elements
as well. Pass %FALSE if you want to free the #GPtrArray wrapper but preserve
-the underlying array for use elsewhere.
+the underlying array for use elsewhere. If the reference count of @array
+is greater than one, the #GPtrArray wrapper is preserved but the size of
+@array will be set to zero.
</para>
<note>
<para>
-If array contents point to dynamically-allocated memory, they should be freed
-separately.
+If array contents point to dynamically-allocated memory, they should
+be freed separately if @free_seg is %TRUE and no #GDestroyNotify
+function has been set for @array.
</para>
</note>
guint elt_size;
guint zero_terminated : 1;
guint clear : 1;
+ volatile gint ref_count;
};
#define g_array_elt_len(array,i) ((array)->elt_size * (i))
array->zero_terminated = (zero_terminated ? 1 : 0);
array->clear = (clear ? 1 : 0);
array->elt_size = elt_size;
+ array->ref_count = 1;
if (array->zero_terminated || reserved_size != 0)
{
return (GArray*) array;
}
+/**
+ * g_array_ref:
+ * @array: A #GArray.
+ *
+ * Atomically increments the reference count of @array by one. This
+ * function is MT-safe and may be called from any thread.
+ *
+ * Returns: The passed in #GArray.
+ *
+ * Since: 2.22
+ **/
+GArray *
+g_array_ref (GArray *array)
+{
+ GRealArray *rarray = (GRealArray*) array;
+ g_return_val_if_fail (g_atomic_int_get (&rarray->ref_count) > 0, array);
+ g_atomic_int_inc (&rarray->ref_count);
+ return array;
+}
+
+/**
+ * g_array_unref:
+ * @array: A #GArray.
+ *
+ * Atomically decrements the reference count of @array by one. If the
+ * reference count drops to 0, all memory allocated by the array is
+ * released. This function is MT-safe and may be called from any
+ * thread.
+ *
+ * Since: 2.22
+ **/
+void
+g_array_unref (GArray *array)
+{
+ GRealArray *rarray = (GRealArray*) array;
+ g_return_if_fail (g_atomic_int_get (&rarray->ref_count) > 0);
+ if (g_atomic_int_dec_and_test (&rarray->ref_count))
+ g_array_free (array, TRUE);
+}
+
+/**
+ * g_array_get_element_size:
+ * @array: A #GArray.
+ *
+ * Gets the size of the elements in @array.
+ *
+ * Returns: Size of each element, in bytes.
+ *
+ * Since: 2.22
+ **/
+guint
+g_array_get_element_size (GArray *array)
+{
+ GRealArray *rarray = (GRealArray*) array;
+ return rarray->elt_size;
+}
+
gchar*
-g_array_free (GArray *array,
+g_array_free (GArray *farray,
gboolean free_segment)
{
+ GRealArray *array = (GRealArray*) farray;
gchar* segment;
+ gboolean preserve_wrapper;
g_return_val_if_fail (array, NULL);
+ /* if others are holding a reference, preserve the wrapper but do free/return the data */
+ preserve_wrapper = FALSE;
+ if (g_atomic_int_get (&array->ref_count) > 1)
+ preserve_wrapper = TRUE;
+
if (free_segment)
{
g_free (array->data);
else
segment = array->data;
- g_slice_free1 (sizeof (GRealArray), array);
+ if (preserve_wrapper)
+ {
+ array->data = NULL;
+ array->len = 0;
+ array->alloc = 0;
+ }
+ else
+ {
+ g_slice_free1 (sizeof (GRealArray), array);
+ }
return segment;
}
struct _GRealPtrArray
{
- gpointer *pdata;
- guint len;
- guint alloc;
+ gpointer *pdata;
+ guint len;
+ guint alloc;
+ volatile gint ref_count;
+ GDestroyNotify element_free_func;
};
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
array->pdata = NULL;
array->len = 0;
array->alloc = 0;
+ array->ref_count = 1;
+ array->element_free_func = NULL;
if (reserved_size != 0)
g_ptr_array_maybe_expand (array, reserved_size);
return (GPtrArray*) array;
}
+/**
+ * g_ptr_array_new_with_free_func:
+ * @element_free_func: A function to free elements with destroy @array or %NULL.
+ *
+ * Creates a new #GPtrArray with a reference count of 1 and use @element_free_func
+ * for freeing each element when the array is destroyed either via
+ * g_ptr_array_unref(), when g_ptr_array_free() is called with @free_segment
+ * set to %TRUE or when removing elements.
+ *
+ * Returns: A new #GPtrArray.
+ *
+ * Since: 2.22
+ **/
+GPtrArray *
+g_ptr_array_new_with_free_func (GDestroyNotify element_free_func)
+{
+ GPtrArray *array;
+
+ array = g_ptr_array_new ();
+ g_ptr_array_set_free_func (array, element_free_func);
+ return array;
+}
+
+/**
+ * g_ptr_array_set_free_func:
+ * @array: A #GPtrArray.
+ * @element_free_func: A function to free elements with destroy @array or %NULL.
+ *
+ * Sets a function for freeing each element when @array is destroyed
+ * either via g_ptr_array_unref(), when g_ptr_array_free() is called
+ * with @free_segment set to %TRUE or when removing elements.
+ *
+ * Since: 2.22
+ **/
+void
+g_ptr_array_set_free_func (GPtrArray *array,
+ GDestroyNotify element_free_func)
+{
+ GRealPtrArray* rarray = (GRealPtrArray*) array;
+ rarray->element_free_func = element_free_func;
+}
+
+/**
+ * g_ptr_array_ref:
+ * @array: A #GArray.
+ *
+ * Atomically increments the reference count of @array by one. This
+ * function is MT-safe and may be called from any thread.
+ *
+ * Returns: The passed in #GPtrArray.
+ *
+ * Since: 2.22
+ **/
+GPtrArray *
+g_ptr_array_ref (GPtrArray *array)
+{
+ GRealPtrArray *rarray = (GRealPtrArray*) array;
+ g_return_val_if_fail (g_atomic_int_get (&rarray->ref_count) > 0, array);
+ g_atomic_int_inc (&rarray->ref_count);
+ return array;
+}
+
+/**
+ * g_ptr_array_unref:
+ * @array: A #GPtrArray.
+ *
+ * Atomically decrements the reference count of @array by one. If the
+ * reference count drops to 0, the effect is the same as calling
+ * g_ptr_array_free() with @free_segment set to %TRUE. This function
+ * is MT-safe and may be called from any thread.
+ *
+ * Since: 2.22
+ **/
+void
+g_ptr_array_unref (GPtrArray *array)
+{
+ GRealPtrArray *rarray = (GRealPtrArray*) array;
+ g_return_if_fail (g_atomic_int_get (&rarray->ref_count) > 0);
+ if (g_atomic_int_dec_and_test (&rarray->ref_count))
+ g_ptr_array_free (array, TRUE);
+}
+
gpointer*
-g_ptr_array_free (GPtrArray *array,
+g_ptr_array_free (GPtrArray *farray,
gboolean free_segment)
{
+ GRealPtrArray *array = (GRealPtrArray*) farray;
gpointer* segment;
+ gboolean preserve_wrapper;
g_return_val_if_fail (array, NULL);
+ /* if others are holding a reference, preserve the wrapper but do free/return the data */
+ preserve_wrapper = FALSE;
+ if (g_atomic_int_get (&array->ref_count) > 1)
+ preserve_wrapper = TRUE;
+
if (free_segment)
{
+ if (array->element_free_func != NULL)
+ g_ptr_array_foreach (farray, (GFunc) array->element_free_func, NULL);
g_free (array->pdata);
segment = NULL;
}
else
segment = array->pdata;
- g_slice_free1 (sizeof (GRealPtrArray), array);
+ if (preserve_wrapper)
+ {
+ array->pdata = NULL;
+ array->len = 0;
+ array->alloc = 0;
+ }
+ else
+ {
+ g_slice_free1 (sizeof (GRealPtrArray), array);
+ }
return segment;
}
result = array->pdata[index_];
+ if (array->element_free_func != NULL)
+ array->element_free_func (array->pdata[index_]);
+
if (index_ != array->len - 1)
g_memmove (array->pdata + index_, array->pdata + index_ + 1,
- sizeof (gpointer) * (array->len - index_ - 1));
+ sizeof (gpointer) * (array->len - index_ - 1));
array->len -= 1;
result = array->pdata[index_];
if (index_ != array->len - 1)
- array->pdata[index_] = array->pdata[array->len - 1];
+ {
+ if (array->element_free_func != NULL)
+ array->element_free_func (array->pdata[index_]);
+ array->pdata[index_] = array->pdata[array->len - 1];
+ }
array->len -= 1;
guint length)
{
GRealPtrArray* array = (GRealPtrArray*) farray;
+ guint n;
g_return_if_fail (array);
g_return_if_fail (index_ < array->len);
g_return_if_fail (index_ + length <= array->len);
+ if (array->element_free_func != NULL)
+ {
+ for (n = index_; n < index_ + length; n++)
+ array->element_free_func (array->pdata[n]);
+ }
+
if (index_ + length != array->len)
- g_memmove (&array->pdata[index_],
- &array->pdata[index_ + length],
- (array->len - (index_ + length)) * sizeof (gpointer));
+ {
+ g_memmove (&array->pdata[index_],
+ &array->pdata[index_ + length],
+ (array->len - (index_ + length)) * sizeof (gpointer));
+ }
array->len -= length;
if (G_UNLIKELY (g_mem_gc_friendly))
return (guint8*) g_array_free ((GArray*) array, free_segment);
}
+/**
+ * g_byte_array_ref:
+ * @array: A #GByteArray.
+ *
+ * Atomically increments the reference count of @array by one. This
+ * function is MT-safe and may be called from any thread.
+ *
+ * Returns: The passed in #GByteArray.
+ *
+ * Since: 2.22
+ **/
+GByteArray *
+g_byte_array_ref (GByteArray *array)
+{
+ return (GByteArray *) g_array_ref ((GArray *) array);
+}
+
+/**
+ * g_byte_array_unref:
+ * @array: A #GByteArray.
+ *
+ * Atomically decrements the reference count of @array by one. If the
+ * reference count drops to 0, all memory allocated by the array is
+ * released. This function is MT-safe and may be called from any
+ * thread.
+ *
+ * Since: 2.22
+ **/
+void
+g_byte_array_unref (GByteArray *array)
+{
+ g_array_unref ((GArray *) array);
+}
+
GByteArray* g_byte_array_append (GByteArray *array,
const guint8 *data,
guint len)
guint reserved_size);
gchar* g_array_free (GArray *array,
gboolean free_segment);
+GArray *g_array_ref (GArray *array);
+void g_array_unref (GArray *array);
+guint g_array_get_element_size (GArray *array);
GArray* g_array_append_vals (GArray *array,
gconstpointer data,
guint len);
*/
#define g_ptr_array_index(array,index_) ((array)->pdata)[index_]
GPtrArray* g_ptr_array_new (void);
+GPtrArray* g_ptr_array_new_with_free_func (GDestroyNotify element_free_func);
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
gpointer* g_ptr_array_free (GPtrArray *array,
gboolean free_seg);
+GPtrArray* g_ptr_array_ref (GPtrArray *array);
+void g_ptr_array_unref (GPtrArray *array);
+void g_ptr_array_set_free_func (GPtrArray *array,
+ GDestroyNotify element_free_func);
void g_ptr_array_set_size (GPtrArray *array,
gint length);
gpointer g_ptr_array_remove_index (GPtrArray *array,
GByteArray* g_byte_array_sized_new (guint reserved_size);
guint8* g_byte_array_free (GByteArray *array,
gboolean free_segment);
+GByteArray *g_byte_array_ref (GByteArray *array);
+void g_byte_array_unref (GByteArray *array);
GByteArray* g_byte_array_append (GByteArray *array,
const guint8 *data,
guint len);
g_array_free
g_array_insert_vals
g_array_new
+g_array_ref
+g_array_unref
+g_array_get_element_size
g_array_prepend_vals
g_array_remove_index
g_array_remove_index_fast
g_array_sort_with_data
g_byte_array_append
g_byte_array_free
+g_byte_array_unref
+g_byte_array_ref
g_byte_array_new
g_byte_array_prepend
g_byte_array_remove_index
g_ptr_array_add
g_ptr_array_foreach
g_ptr_array_free
+g_ptr_array_unref
+g_ptr_array_ref
g_ptr_array_new
+g_ptr_array_new_with_free_func
+g_ptr_array_set_free_func
g_ptr_array_remove
g_ptr_array_remove_fast
g_ptr_array_remove_index
}
static void
+array_ref_count (void)
+{
+ GArray *garray;
+ GArray *garray2;
+ gint i;
+
+ garray = g_array_new (FALSE, FALSE, sizeof (gint));
+ g_assert_cmpint (g_array_get_element_size (garray), ==, sizeof (gint));
+ for (i = 0; i < 100; i++)
+ g_array_prepend_val (garray, i);
+
+ /* check we can ref, unref and still access the array */
+ garray2 = g_array_ref (garray);
+ g_assert (garray == garray2);
+ g_array_unref (garray2);
+ for (i = 0; i < 100; i++)
+ g_assert_cmpint (g_array_index (garray, gint, i), ==, (100 - i - 1));
+
+ /* garray2 should be an empty valid GArray wrapper */
+ garray2 = g_array_ref (garray);
+ g_array_free (garray, TRUE);
+
+ g_assert_cmpint (garray2->len, ==, 0);
+ g_array_unref (garray2);
+}
+
+static void
pointer_array_add (void)
{
GPtrArray *gparray;
}
static void
+pointer_array_ref_count (void)
+{
+ GPtrArray *gparray;
+ GPtrArray *gparray2;
+ gint i;
+ gint sum = 0;
+
+ gparray = g_ptr_array_new ();
+ for (i = 0; i < 10000; i++)
+ g_ptr_array_add (gparray, GINT_TO_POINTER (i));
+
+ /* check we can ref, unref and still access the array */
+ gparray2 = g_ptr_array_ref (gparray);
+ g_assert (gparray == gparray2);
+ g_ptr_array_unref (gparray2);
+ for (i = 0; i < 10000; i++)
+ g_assert (g_ptr_array_index (gparray, i) == GINT_TO_POINTER (i));
+
+ g_ptr_array_foreach (gparray, sum_up, &sum);
+ g_assert (sum == 49995000);
+
+ /* gparray2 should be an empty valid GPtrArray wrapper */
+ gparray2 = g_ptr_array_ref (gparray);
+ g_ptr_array_free (gparray, TRUE);
+
+ g_assert_cmpint (gparray2->len, ==, 0);
+ g_ptr_array_unref (gparray2);
+}
+
+static gint num_free_func_invocations = 0;
+
+static void
+my_free_func (gpointer data)
+{
+ num_free_func_invocations++;
+ g_free (data);
+}
+
+static void
+pointer_array_free_func (void)
+{
+ GPtrArray *gparray;
+ GPtrArray *gparray2;
+ gchar **strv;
+ gchar *s;
+
+ num_free_func_invocations = 0;
+ gparray = g_ptr_array_new_with_free_func (my_free_func);
+ g_ptr_array_unref (gparray);
+ g_assert_cmpint (num_free_func_invocations, ==, 0);
+
+ gparray = g_ptr_array_new_with_free_func (my_free_func);
+ g_ptr_array_free (gparray, TRUE);
+ g_assert_cmpint (num_free_func_invocations, ==, 0);
+
+ num_free_func_invocations = 0;
+ gparray = g_ptr_array_new_with_free_func (my_free_func);
+ g_ptr_array_add (gparray, g_strdup ("foo"));
+ g_ptr_array_add (gparray, g_strdup ("bar"));
+ g_ptr_array_add (gparray, g_strdup ("baz"));
+ g_ptr_array_remove_index (gparray, 0);
+ g_assert_cmpint (num_free_func_invocations, ==, 1);
+ s = g_strdup ("frob");
+ g_ptr_array_add (gparray, s);
+ g_assert (g_ptr_array_remove (gparray, s));
+ g_assert_cmpint (num_free_func_invocations, ==, 2);
+ g_ptr_array_ref (gparray);
+ g_ptr_array_unref (gparray);
+ g_assert_cmpint (num_free_func_invocations, ==, 2);
+ g_ptr_array_unref (gparray);
+ g_assert_cmpint (num_free_func_invocations, ==, 4);
+
+ num_free_func_invocations = 0;
+ gparray = g_ptr_array_new_with_free_func (my_free_func);
+ g_ptr_array_add (gparray, g_strdup ("foo"));
+ g_ptr_array_add (gparray, g_strdup ("bar"));
+ g_ptr_array_add (gparray, g_strdup ("baz"));
+ g_ptr_array_add (gparray, NULL);
+ gparray2 = g_ptr_array_ref (gparray);
+ strv = (gchar **) g_ptr_array_free (gparray, FALSE);
+ g_assert_cmpint (num_free_func_invocations, ==, 0);
+ g_strfreev (strv);
+ g_ptr_array_unref (gparray2);
+ g_assert_cmpint (num_free_func_invocations, ==, 0);
+
+ num_free_func_invocations = 0;
+ gparray = g_ptr_array_new_with_free_func (my_free_func);
+ g_ptr_array_add (gparray, g_strdup ("foo"));
+ g_ptr_array_add (gparray, g_strdup ("bar"));
+ g_ptr_array_add (gparray, g_strdup ("baz"));
+ g_ptr_array_unref (gparray);
+ g_assert_cmpint (num_free_func_invocations, ==, 3);
+
+ num_free_func_invocations = 0;
+ gparray = g_ptr_array_new_with_free_func (my_free_func);
+ g_ptr_array_add (gparray, g_strdup ("foo"));
+ g_ptr_array_add (gparray, g_strdup ("bar"));
+ g_ptr_array_add (gparray, g_strdup ("baz"));
+ g_ptr_array_free (gparray, TRUE);
+ g_assert_cmpint (num_free_func_invocations, ==, 3);
+
+ num_free_func_invocations = 0;
+ gparray = g_ptr_array_new_with_free_func (my_free_func);
+ g_ptr_array_add (gparray, "foo");
+ g_ptr_array_add (gparray, "bar");
+ g_ptr_array_add (gparray, "baz");
+ g_ptr_array_set_free_func (gparray, NULL);
+ g_ptr_array_free (gparray, TRUE);
+ g_assert_cmpint (num_free_func_invocations, ==, 0);
+}
+
+static void
byte_array_append (void)
{
GByteArray *gbarray;
g_byte_array_free (gbarray, TRUE);
}
+static void
+byte_array_ref_count (void)
+{
+ GByteArray *gbarray;
+ GByteArray *gbarray2;
+ gint i;
+
+ gbarray = g_byte_array_new ();
+ for (i = 0; i < 10000; i++)
+ g_byte_array_append (gbarray, (guint8*) "abcd", 4);
+
+ gbarray2 = g_byte_array_ref (gbarray);
+ g_assert (gbarray2 == gbarray);
+ g_byte_array_unref (gbarray2);
+ for (i = 0; i < 10000; i++)
+ {
+ g_assert (gbarray->data[4*i] == 'a');
+ g_assert (gbarray->data[4*i+1] == 'b');
+ g_assert (gbarray->data[4*i+2] == 'c');
+ g_assert (gbarray->data[4*i+3] == 'd');
+ }
+
+ gbarray2 = g_byte_array_ref (gbarray);
+ g_assert (gbarray2 == gbarray);
+ g_byte_array_free (gbarray, TRUE);
+ g_assert_cmpint (gbarray2->len, ==, 0);
+ g_byte_array_unref (gbarray2);
+}
+
int
main (int argc, char *argv[])
{
/* array tests */
g_test_add_func ("/array/append", array_append);
g_test_add_func ("/array/prepend", array_prepend);
+ g_test_add_func ("/array/ref-count", array_ref_count);
/* pointer arrays */
g_test_add_func ("/pointerarray/add", pointer_array_add);
+ g_test_add_func ("/pointerarray/ref-count", pointer_array_ref_count);
+ g_test_add_func ("/pointerarray/free-func", pointer_array_free_func);
/* byte arrays */
g_test_add_func ("/bytearray/append", byte_array_append);
+ g_test_add_func ("/bytearray/ref-count", byte_array_ref_count);
return g_test_run ();
}
return type_id;
}
+GType
+g_array_get_type (void)
+{
+ static GType type_id = 0;
+ if (!type_id)
+ type_id = g_boxed_type_register_static (g_intern_static_string ("GArray"),
+ (GBoxedCopyFunc) g_array_ref,
+ (GBoxedFreeFunc) g_array_unref);
+ return type_id;
+}
+
+GType
+g_ptr_array_get_type (void)
+{
+ static GType type_id = 0;
+ if (!type_id)
+ type_id = g_boxed_type_register_static (g_intern_static_string ("GPtrArray"),
+ (GBoxedCopyFunc) g_ptr_array_ref,
+ (GBoxedFreeFunc) g_ptr_array_unref);
+ return type_id;
+}
+
+GType
+g_byte_array_get_type (void)
+{
+ static GType type_id = 0;
+ if (!type_id)
+ type_id = g_boxed_type_register_static (g_intern_static_string ("GByteArray"),
+ (GBoxedCopyFunc) g_byte_array_ref,
+ (GBoxedFreeFunc) g_byte_array_unref);
+ return type_id;
+}
+
static void
boxed_proxy_value_init (GValue *value)
{
* Since: 2.14
*/
#define G_TYPE_REGEX (g_regex_get_type ())
+/**
+ * G_TYPE_ARRAY:
+ *
+ * The #GType for a boxed type holding a #GArray reference.
+ *
+ * Since: 2.22
+ */
+#define G_TYPE_ARRAY (g_array_get_type ())
+/**
+ * G_TYPE_BYTE_ARRAY:
+ *
+ * The #GType for a boxed type holding a #GByteArray reference.
+ *
+ * Since: 2.22
+ */
+#define G_TYPE_BYTE_ARRAY (g_byte_array_get_type ())
+/**
+ * G_TYPE_PTR_ARRAY:
+ *
+ * The #GType for a boxed type holding a #GPtrArray reference.
+ *
+ * Since: 2.22
+ */
+#define G_TYPE_PTR_ARRAY (g_ptr_array_get_type ())
void g_value_take_boxed (GValue *value,
GType g_strv_get_type (void) G_GNUC_CONST;
GType g_gstring_get_type (void) G_GNUC_CONST;
GType g_hash_table_get_type (void) G_GNUC_CONST;
+GType g_array_get_type (void) G_GNUC_CONST;
+GType g_byte_array_get_type (void) G_GNUC_CONST;
+GType g_ptr_array_get_type (void) G_GNUC_CONST;
GType g_regex_get_type (void) G_GNUC_CONST;
/**
g_gstring_get_type G_GNUC_CONST
g_strv_get_type G_GNUC_CONST
g_hash_table_get_type G_GNUC_CONST
+g_array_get_type G_GNUC_CONST
+g_byte_array_get_type G_GNUC_CONST
+g_ptr_array_get_type G_GNUC_CONST
g_regex_get_type G_GNUC_CONST
g_closure_get_type G_GNUC_CONST
g_value_get_type G_GNUC_CONST