mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 07:56:14 +01:00
Make g_rc_box_dup()/g_arc_box_dup() more generic
It's more useful to have a dup() function that copies any blob of memory into a reference counted allocation, than to have a dup() that only copies a reference counted allocation.
This commit is contained in:
parent
b607927a43
commit
8990c3c4d3
@ -222,29 +222,28 @@ g_arc_box_alloc0 (gsize block_size)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* g_arc_box_dup:
|
* g_arc_box_dup:
|
||||||
* @mem_block: (not nullable): a pointer to reference counted data
|
* @block_size: the number of bytes to copy
|
||||||
|
* @mem_block: (not nullable): the memory to copy
|
||||||
*
|
*
|
||||||
* Allocates a new block of data with atomic reference counting
|
* Allocates a new block of data with atomit reference counting
|
||||||
* semantics, and copies the contents of @mem_block into
|
* semantics, and copies @block_size bytes of @mem_block
|
||||||
* it.
|
* into it.
|
||||||
*
|
*
|
||||||
* Returns: (not nullable): a pointer to the allocated memory
|
* Returns: (not nullable): a pointer to the allocated memory
|
||||||
*
|
*
|
||||||
* Since: 2.58
|
* Since: 2.58
|
||||||
*/
|
*/
|
||||||
gpointer
|
gpointer
|
||||||
(g_arc_box_dup) (gpointer mem_block)
|
(g_arc_box_dup) (gsize block_size,
|
||||||
|
gconstpointer mem_block)
|
||||||
{
|
{
|
||||||
GArcBox *real_box = G_ARC_BOX (mem_block);
|
|
||||||
gpointer res;
|
gpointer res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (block_size > 0, NULL);
|
||||||
g_return_val_if_fail (mem_block != NULL, NULL);
|
g_return_val_if_fail (mem_block != NULL, NULL);
|
||||||
#ifndef G_DISABLE_ASSERT
|
|
||||||
g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
res = g_rc_box_alloc_full (real_box->mem_size, TRUE, FALSE);
|
res = g_rc_box_alloc_full (block_size, TRUE, FALSE);
|
||||||
memcpy (res, mem_block, real_box->mem_size);
|
memcpy (res, mem_block, block_size);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -286,29 +286,28 @@ g_rc_box_alloc0 (gsize block_size)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* g_rc_box_dup:
|
* g_rc_box_dup:
|
||||||
* @mem_block: (not nullable): a pointer to reference counted data
|
* @block_size: the number of bytes to copy
|
||||||
|
* @mem_block: (not nullable): the memory to copy
|
||||||
*
|
*
|
||||||
* Allocates a new block of data with reference counting
|
* Allocates a new block of data with reference counting
|
||||||
* semantics, and copies the contents of @mem_block into
|
* semantics, and copies @block_size bytes of @mem_block
|
||||||
* it.
|
* into it.
|
||||||
*
|
*
|
||||||
* Returns: (not nullable): a pointer to the allocated memory
|
* Returns: (not nullable): a pointer to the allocated memory
|
||||||
*
|
*
|
||||||
* Since: 2.58
|
* Since: 2.58
|
||||||
*/
|
*/
|
||||||
gpointer
|
gpointer
|
||||||
(g_rc_box_dup) (gpointer mem_block)
|
(g_rc_box_dup) (gsize block_size,
|
||||||
|
gconstpointer mem_block)
|
||||||
{
|
{
|
||||||
GRcBox *real_box = G_RC_BOX (mem_block);
|
|
||||||
gpointer res;
|
gpointer res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (block_size > 0, NULL);
|
||||||
g_return_val_if_fail (mem_block != NULL, NULL);
|
g_return_val_if_fail (mem_block != NULL, NULL);
|
||||||
#ifndef G_DISABLE_ASSERT
|
|
||||||
g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
res = g_rc_box_alloc_full (real_box->mem_size, FALSE, FALSE);
|
res = g_rc_box_alloc_full (block_size, FALSE, FALSE);
|
||||||
memcpy (res, mem_block, real_box->mem_size);
|
memcpy (res, mem_block, block_size);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ gpointer g_rc_box_alloc (gsize block_size) G_GNUC_MALL
|
|||||||
GLIB_AVAILABLE_IN_2_58
|
GLIB_AVAILABLE_IN_2_58
|
||||||
gpointer g_rc_box_alloc0 (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
gpointer g_rc_box_alloc0 (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
||||||
GLIB_AVAILABLE_IN_2_58
|
GLIB_AVAILABLE_IN_2_58
|
||||||
gpointer g_rc_box_dup (gpointer mem_block) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
gpointer g_rc_box_dup (gsize block_size,
|
||||||
|
gconstpointer mem_block) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
||||||
GLIB_AVAILABLE_IN_2_58
|
GLIB_AVAILABLE_IN_2_58
|
||||||
gpointer g_rc_box_acquire (gpointer mem_block);
|
gpointer g_rc_box_acquire (gpointer mem_block);
|
||||||
GLIB_AVAILABLE_IN_2_58
|
GLIB_AVAILABLE_IN_2_58
|
||||||
@ -45,7 +46,8 @@ gpointer g_arc_box_alloc (gsize block_size) G_GNUC_MALL
|
|||||||
GLIB_AVAILABLE_IN_2_58
|
GLIB_AVAILABLE_IN_2_58
|
||||||
gpointer g_arc_box_alloc0 (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
gpointer g_arc_box_alloc0 (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
||||||
GLIB_AVAILABLE_IN_2_58
|
GLIB_AVAILABLE_IN_2_58
|
||||||
gpointer g_arc_box_dup (gpointer mem_block) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
gpointer g_arc_box_dup (gsize block_size,
|
||||||
|
gconstpointer mem_block) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
||||||
GLIB_AVAILABLE_IN_2_58
|
GLIB_AVAILABLE_IN_2_58
|
||||||
gpointer g_arc_box_acquire (gpointer mem_block);
|
gpointer g_arc_box_acquire (gpointer mem_block);
|
||||||
GLIB_AVAILABLE_IN_2_58
|
GLIB_AVAILABLE_IN_2_58
|
||||||
@ -71,10 +73,10 @@ void g_arc_box_release_full (gpointer mem_block,
|
|||||||
((__typeof__(mem_block)) (g_arc_box_acquire) (mem_block))
|
((__typeof__(mem_block)) (g_arc_box_acquire) (mem_block))
|
||||||
|
|
||||||
/* Type check to avoid duplicating data to different types */
|
/* Type check to avoid duplicating data to different types */
|
||||||
# define g_rc_box_dup(mem_block) \
|
# define g_rc_box_dup(block_size,mem_block) \
|
||||||
((__typeof__(mem_block)) (g_rc_box_dup) (mem_block))
|
((__typeof__(mem_block)) (g_rc_box_dup) (block_size,mem_block))
|
||||||
# define g_arc_box_dup(mem_block) \
|
# define g_arc_box_dup(block_size,mem_block) \
|
||||||
((__typeof__(mem_block)) (g_arc_box_dup) (mem_block))
|
((__typeof__(mem_block)) (g_arc_box_dup) (block_size,mem_block))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/* rcbox.c: Reference counted data
|
||||||
|
*
|
||||||
|
* Copyright 2018 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -6,6 +24,7 @@ typedef struct {
|
|||||||
|
|
||||||
static Point *global_point;
|
static Point *global_point;
|
||||||
|
|
||||||
|
/* test_rcbox_new: Test g_rc_box_new() */
|
||||||
static void
|
static void
|
||||||
test_rcbox_new (void)
|
test_rcbox_new (void)
|
||||||
{
|
{
|
||||||
@ -27,14 +46,18 @@ static void
|
|||||||
point_clear (Point *p)
|
point_clear (Point *p)
|
||||||
{
|
{
|
||||||
g_assert_nonnull (p);
|
g_assert_nonnull (p);
|
||||||
|
g_assert_true (global_point == p);
|
||||||
|
|
||||||
g_assert_cmpfloat (p->x, ==, 42.0f);
|
g_assert_cmpfloat (p->x, ==, 42.0f);
|
||||||
g_assert_cmpfloat (p->y, ==, 47.0f);
|
g_assert_cmpfloat (p->y, ==, 47.0f);
|
||||||
|
|
||||||
g_assert_true (global_point == p);
|
g_test_message ("global_point = %p", p);
|
||||||
global_point = NULL;
|
global_point = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* test_rcbox_release_full: Verify that g_rc_box_release_full() calls
|
||||||
|
* the clear function only when the last reference is released
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
test_rcbox_release_full (void)
|
test_rcbox_release_full (void)
|
||||||
{
|
{
|
||||||
@ -56,16 +79,63 @@ test_rcbox_release_full (void)
|
|||||||
g_assert_null (global_point);
|
g_assert_null (global_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Point *global_point_a;
|
||||||
|
static Point *global_point_b;
|
||||||
|
|
||||||
|
static void
|
||||||
|
point_clear_dup_a (Point *a)
|
||||||
|
{
|
||||||
|
g_assert_true (a == global_point_a);
|
||||||
|
|
||||||
|
g_test_message ("global_point_a = %p", a);
|
||||||
|
global_point_a = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
point_clear_dup_b (Point *b)
|
||||||
|
{
|
||||||
|
g_assert_true (b == global_point_b);
|
||||||
|
|
||||||
|
g_test_message ("global_point_b = %p", b);
|
||||||
|
global_point_b = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test_rcbox_dup: Verify that g_rc_box_dup() copies only the
|
||||||
|
* data and does not change the reference count of the original
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
test_rcbox_dup (void)
|
test_rcbox_dup (void)
|
||||||
{
|
{
|
||||||
Point *a = g_rc_box_new (Point);
|
Point *a, *b;
|
||||||
Point *b = g_rc_box_dup (a);
|
|
||||||
|
|
||||||
|
a = g_rc_box_new (Point);
|
||||||
|
a->x = 10.f;
|
||||||
|
a->y = 5.f;
|
||||||
|
|
||||||
|
b = g_rc_box_dup (sizeof (Point), a);
|
||||||
g_assert_true (a != b);
|
g_assert_true (a != b);
|
||||||
|
g_assert_cmpfloat (a->x, ==, b->x);
|
||||||
|
g_assert_cmpfloat (a->y, ==, b->y);
|
||||||
|
|
||||||
g_rc_box_release (a);
|
global_point_a = a;
|
||||||
g_rc_box_release (b);
|
global_point_b = b;
|
||||||
|
|
||||||
|
a->x = 1.f;
|
||||||
|
a->y = 1.f;
|
||||||
|
g_assert_cmpfloat (a->x, !=, b->x);
|
||||||
|
g_assert_cmpfloat (a->y, !=, b->y);
|
||||||
|
|
||||||
|
b->x = 5.f;
|
||||||
|
b->y = 10.f;
|
||||||
|
g_assert_cmpfloat (a->x, !=, b->x);
|
||||||
|
g_assert_cmpfloat (a->y, !=, b->y);
|
||||||
|
|
||||||
|
g_rc_box_release_full (a, (GDestroyNotify) point_clear_dup_a);
|
||||||
|
g_assert_null (global_point_a);
|
||||||
|
g_assert_nonnull (global_point_b);
|
||||||
|
|
||||||
|
g_rc_box_release_full (b, (GDestroyNotify) point_clear_dup_b);
|
||||||
|
g_assert_null (global_point_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -75,8 +145,8 @@ main (int argc,
|
|||||||
g_test_init (&argc, &argv, NULL);
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
g_test_add_func ("/rcbox/new", test_rcbox_new);
|
g_test_add_func ("/rcbox/new", test_rcbox_new);
|
||||||
g_test_add_func ("/rcbox/dup", test_rcbox_dup);
|
|
||||||
g_test_add_func ("/rcbox/release-full", test_rcbox_release_full);
|
g_test_add_func ("/rcbox/release-full", test_rcbox_release_full);
|
||||||
|
g_test_add_func ("/rcbox/dup", test_rcbox_dup);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user