summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-07-02 23:46:06 +0200
committerThomas Haller <thaller@redhat.com>2017-07-05 18:37:39 +0200
commit28340588d9cbca3eed1f75a9d10b6a0b19068004 (patch)
tree0395f5cd6b224a279fe9a57d8e84d9a006af1d32
parent667c50f5d920e91d798d51c61e63e3ce87e277d3 (diff)
downloadNetworkManager-28340588d9cbca3eed1f75a9d10b6a0b19068004.tar.gz
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of NMDedupMultiObj and get rid of NMDedupMultiBox. With this change, the NMPObject is aware in which NMDedupMultiIndex instance it is tracked. - this saves an additional GSlice allocation for the NMDedupMultiBox. - it is immediately known, whether an NMPObject is tracked by a certain NMDedupMultiIndex or not. This saves an additional hash lookup. - previously, when all idx-types cease to reference an NMDedupMultiObj instance, it was removed. Now, a tracked objects stays in the NMDedupMultiIndex until it's last reference is deleted. This possibly extends the lifetime of the object and we may reuse it better. - it is no longer possible to add one object to more then one NMDedupMultiIndex instance. As we anyway want to have only one instance to deduplicate the objects, this is fine. - the ref-counting implementation is now part of NMDedupMultiObj. Previously, NMDedupMultiIndex could also track objects that were not ref-counted. Hoever, the object anyway *must* implement the NMDedupMultiObj API, so this flexibility is unneeded and was not used. - a downside is, that NMPObject grows by one pointer size, even if it isn't tracked in the NMDedupMultiIndex. But we really want to put all objects into the index for sharing and deduplication. So this downside should be acceptable. Still, code like nmp_object_stackinit*() needs to handle a larger object.
-rw-r--r--libnm-core/tests/test-general.c54
-rw-r--r--shared/nm-utils/nm-dedup-multi.c287
-rw-r--r--shared/nm-utils/nm-dedup-multi.h42
-rw-r--r--src/nm-ip4-config.c18
-rw-r--r--src/platform/nm-linux-platform.c2
-rw-r--r--src/platform/nmp-object.c214
-rw-r--r--src/platform/nmp-object.h39
-rw-r--r--src/platform/tests/test-nmp-object.c19
8 files changed, 340 insertions, 335 deletions
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index a897fe5a4e..db261adfec 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -78,7 +78,6 @@ G_STATIC_ASSERT (sizeof (bool) <= sizeof (int));
typedef struct {
NMDedupMultiObj parent;
- int ref_count;
guint val;
guint other;
} DedupObj;
@@ -93,39 +92,34 @@ _dedup_obj_assert (const NMDedupMultiObj *obj)
g_assert (obj);
o = (DedupObj *) obj;
g_assert (o->parent.klass == &dedup_obj_class);
- g_assert (o->ref_count > 0);
+ g_assert (o->parent._ref_count > 0);
g_assert (o->val > 0);
return o;
}
-static NMDedupMultiObj *
-_dedup_obj_get_ref (const NMDedupMultiObj *obj)
+static const NMDedupMultiObj *
+_dedup_obj_clone (const NMDedupMultiObj *obj)
{
DedupObj *o, *o2;
o = _dedup_obj_assert (obj);
- if (o->ref_count == NM_OBJ_REF_COUNT_STACKINIT) {
- o2 = g_slice_new0 (DedupObj);
- o2->parent.klass = &dedup_obj_class;
- o2->ref_count = 1;
- o2->val = o->val;
- o2->other = o->other;
- return (NMDedupMultiObj *) o2;
- }
-
- o->ref_count++;
- return (NMDedupMultiObj *) o;
+ o2 = g_slice_new0 (DedupObj);
+ o2->parent.klass = &dedup_obj_class;
+ o2->parent._ref_count = 1;
+ o2->val = o->val;
+ o2->other = o->other;
+ return (NMDedupMultiObj *) o2;
}
static void
-_dedup_obj_put_ref (NMDedupMultiObj *obj)
+_dedup_obj_destroy (NMDedupMultiObj *obj)
{
- DedupObj *o;
+ DedupObj *o = (DedupObj *) obj;
+ nm_assert (o->parent._ref_count == 0);
+ o->parent._ref_count = 1;
o = _dedup_obj_assert (obj);
- g_assert (o->ref_count != NM_OBJ_REF_COUNT_STACKINIT);
- if (--o->ref_count == 0)
- g_slice_free (DedupObj, o);
+ g_slice_free (DedupObj, o);
}
static guint
@@ -149,8 +143,8 @@ _dedup_obj_full_equal (const NMDedupMultiObj *obj_a,
}
static const NMDedupMultiObjClass dedup_obj_class = {
- .obj_get_ref = _dedup_obj_get_ref,
- .obj_put_ref = _dedup_obj_put_ref,
+ .obj_clone = _dedup_obj_clone,
+ .obj_destroy = _dedup_obj_destroy,
.obj_full_equality_allows_different_class = FALSE,
.obj_full_hash = _dedup_obj_full_hash,
.obj_full_equal = _dedup_obj_full_equal,
@@ -160,8 +154,8 @@ static const NMDedupMultiObjClass dedup_obj_class = {
(&((DedupObj) { \
.parent = { \
.klass = &dedup_obj_class, \
+ ._ref_count = NM_OBJ_REF_COUNT_STACKINIT, \
}, \
- .ref_count = NM_OBJ_REF_COUNT_STACKINIT, \
.val = (val_val), \
.other = (other_other), \
}))
@@ -295,7 +289,7 @@ _dedup_entry_assert (const NMDedupMultiEntry *entry)
g_assert (!entry->is_head);
g_assert (entry->head != (gpointer) entry);
_dedup_head_entry_assert (entry->head);
- return _dedup_obj_assert (entry->box->obj);
+ return _dedup_obj_assert (entry->obj);
}
static const DedupIdxType *
@@ -341,8 +335,8 @@ _dedup_entry_assert_all (const NMDedupMultiEntry *entry, gssize expected_idx, co
if (expected_idx == i)
g_assert (entry_current == entry);
g_assert (idx_type->parent.klass->idx_obj_partition_equal (&idx_type->parent,
- entry_current->box->obj,
- c_list_entry (entry->head->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->box->obj));
+ entry_current->obj,
+ c_list_entry (entry->head->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj));
i++;
}
}
@@ -361,14 +355,14 @@ test_dedup_multi (void)
g_assert (_dedup_idx_add (idx, IDX_20_3_a, DEDUP_OBJ_INIT (1, 1), NM_DEDUP_MULTI_IDX_MODE_APPEND, &entry1));
_dedup_entry_assert_all (entry1, 0, DEDUP_OBJ_INIT (1, 1));
- g_assert (nm_dedup_multi_box_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 1)));
- g_assert (!nm_dedup_multi_box_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 2)));
+ g_assert (nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 1)));
+ g_assert (!nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 2)));
g_assert (_dedup_idx_add (idx, IDX_20_3_a, DEDUP_OBJ_INIT (1, 2), NM_DEDUP_MULTI_IDX_MODE_APPEND, &entry1));
_dedup_entry_assert_all (entry1, 0, DEDUP_OBJ_INIT (1, 2));
- g_assert (!nm_dedup_multi_box_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 1)));
- g_assert (nm_dedup_multi_box_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 2)));
+ g_assert (!nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 1)));
+ g_assert (nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 2)));
g_assert (_dedup_idx_add (idx, IDX_20_3_a, DEDUP_OBJ_INIT (2, 2), NM_DEDUP_MULTI_IDX_MODE_APPEND, &entry1));
_dedup_entry_assert_all (entry1, 1, DEDUP_OBJ_INIT (1, 2), DEDUP_OBJ_INIT (2, 2));
diff --git a/shared/nm-utils/nm-dedup-multi.c b/shared/nm-utils/nm-dedup-multi.c
index 6e949f9066..6a276ae4f1 100644
--- a/shared/nm-utils/nm-dedup-multi.c
+++ b/shared/nm-utils/nm-dedup-multi.c
@@ -26,11 +26,6 @@
/*****************************************************************************/
typedef struct {
- NMDedupMultiBox parent;
- int ref_count;
-} Box;
-
-typedef struct {
/* the stack-allocated lookup entry. It has a compatible
* memory layout with NMDedupMultiEntry and NMDedupMultiHeadEntry.
*
@@ -47,16 +42,11 @@ typedef struct {
struct _NMDedupMultiIndex {
int ref_count;
GHashTable *idx_entries;
- GHashTable *idx_box;
+ GHashTable *idx_objs;
};
/*****************************************************************************/
-static void _box_unref (NMDedupMultiIndex *self,
- Box *box);
-
-/*****************************************************************************/
-
static void
ASSERT_idx_type (const NMDedupMultiIdxType *idx_type)
{
@@ -142,7 +132,7 @@ _entry_unpack (const NMDedupMultiEntry *entry,
G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (LookupEntry, lst_entries_sentinel) == G_STRUCT_OFFSET (NMDedupMultiEntry, lst_entries));
G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, lst_entries) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, lst_entries_head));
- G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, box) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, idx_type));
+ G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, obj) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, idx_type));
G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, is_head) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, is_head));
if (!entry->lst_entries.next) {
@@ -154,11 +144,11 @@ _entry_unpack (const NMDedupMultiEntry *entry,
} else if (entry->is_head) {
head_entry = (NMDedupMultiHeadEntry *) entry;
nm_assert (!c_list_is_empty (&head_entry->lst_entries_head));
- *out_obj = c_list_entry (head_entry->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->box->obj;
+ *out_obj = c_list_entry (head_entry->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj;
*out_idx_type = head_entry->idx_type;
*out_lookup_head = TRUE;
} else {
- *out_obj = entry->box->obj;
+ *out_obj = entry->obj;
*out_idx_type = entry->head->idx_type;
*out_lookup_head = FALSE;
}
@@ -223,12 +213,11 @@ _add (NMDedupMultiIndex *self,
NMDedupMultiIdxMode mode,
const NMDedupMultiEntry *entry_order,
NMDedupMultiHeadEntry *head_existing,
- const NMDedupMultiBox *box_existing,
const NMDedupMultiEntry **out_entry,
- const NMDedupMultiBox **out_old_box)
+ const NMDedupMultiObj **out_obj_old)
{
NMDedupMultiHeadEntry *head_entry;
- const NMDedupMultiBox *box, *box_new;
+ const NMDedupMultiObj *obj_new, *obj_old;
gboolean add_head_entry = FALSE;
nm_assert (self);
@@ -239,7 +228,6 @@ _add (NMDedupMultiIndex *self,
NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
NM_DEDUP_MULTI_IDX_MODE_APPEND,
NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE));
- nm_assert (!box_existing || box_existing == nm_dedup_multi_box_find (self, obj));
nm_assert (!head_existing || head_existing->idx_type == idx_type);
nm_assert (({
const NMDedupMultiHeadEntry *_h;
@@ -299,27 +287,24 @@ _add (NMDedupMultiIndex *self,
break;
};
- if ( obj == entry->box->obj
+ if ( obj == entry->obj
|| obj->klass->obj_full_equal (obj,
- entry->box->obj)) {
+ entry->obj)) {
NM_SET_OUT (out_entry, entry);
- NM_SET_OUT (out_old_box, nm_dedup_multi_box_ref (entry->box));
+ NM_SET_OUT (out_obj_old, nm_dedup_multi_obj_ref (entry->obj));
return FALSE;
}
- if (box_existing)
- box_new = nm_dedup_multi_box_ref (box_existing);
- else
- box_new = nm_dedup_multi_box_new (self, obj);
+ obj_new = nm_dedup_multi_index_obj_intern (self, obj);
- box = entry->box;
- entry->box = box_new;
+ obj_old = entry->obj;
+ entry->obj = obj_new;
NM_SET_OUT (out_entry, entry);
- if (out_old_box)
- *out_old_box = box;
+ if (out_obj_old)
+ *out_obj_old = obj_old;
else
- _box_unref (self, (Box *) box);
+ nm_dedup_multi_obj_unref (obj_old);
return TRUE;
}
@@ -328,18 +313,14 @@ _add (NMDedupMultiIndex *self,
/* this object cannot be partitioned by this idx_type. */
nm_assert (!head_existing || head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING);
NM_SET_OUT (out_entry, NULL);
- NM_SET_OUT (out_old_box, NULL);
+ NM_SET_OUT (out_obj_old, NULL);
return FALSE;
}
- if (box_existing)
- box_new = nm_dedup_multi_box_ref (box_existing);
- else
- box_new = nm_dedup_multi_box_new (self, obj);
- obj = box_new->obj;
+ obj_new = nm_dedup_multi_index_obj_intern (self, obj);
if (!head_existing)
- head_entry = _entry_lookup_head (self, idx_type, obj);
+ head_entry = _entry_lookup_head (self, idx_type, obj_new);
else if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
head_entry = NULL;
else
@@ -363,7 +344,7 @@ _add (NMDedupMultiIndex *self,
}
entry = g_slice_new0 (NMDedupMultiEntry);
- entry->box = box_new;
+ entry->obj = obj_new;
entry->head = head_entry;
switch (mode) {
@@ -393,7 +374,7 @@ _add (NMDedupMultiIndex *self,
nm_assert_not_reached ();
NM_SET_OUT (out_entry, entry);
- NM_SET_OUT (out_old_box, NULL);
+ NM_SET_OUT (out_obj_old, NULL);
return TRUE;
}
@@ -403,7 +384,7 @@ nm_dedup_multi_index_add (NMDedupMultiIndex *self,
/*const NMDedupMultiObj * */ gconstpointer obj,
NMDedupMultiIdxMode mode,
const NMDedupMultiEntry **out_entry,
- const NMDedupMultiBox **out_old_box)
+ /* const NMDedupMultiObj ** */ gpointer out_obj_old)
{
NMDedupMultiEntry *entry;
@@ -419,9 +400,9 @@ nm_dedup_multi_index_add (NMDedupMultiIndex *self,
entry = _entry_lookup_obj (self, idx_type, obj);
return _add (self, idx_type, obj,
- entry, mode, NULL,
+ entry, mode,
NULL, NULL,
- out_entry, out_old_box);
+ out_entry, out_obj_old);
}
/* nm_dedup_multi_index_add_full:
@@ -446,16 +427,13 @@ nm_dedup_multi_index_add (NMDedupMultiIndex *self,
* @head_existing: an optional argument to safe a lookup for the head. If specified,
* it must be identical to nm_dedup_multi_index_lookup_head(), with the pecularity
* that if the head is not yet tracked, you may specify %NM_DEDUP_MULTI_HEAD_ENTRY_MISSING
- * @box_existing: optional argument to safe the box lookup. If given, @obj and the boxed
- * object must be identical, and @box_existing must be tracked by @self. This is to safe
- * the additional lookup.
* @out_entry: if give, return the added entry. This entry may have already exists (update)
* or be newly created. If @obj is not partitionable according to @idx_type, @obj
* is not to be added and it returns %NULL.
- * @out_old_box: if given, return the previously contained boxed object. It only
- * returns a boxed object, if a matching entry was tracked previously, not if a
- * new entry was created. Note that when passing @out_old_box you obtain a reference
- * to the boxed object and MUST return it with nm_dedup_multi_box_unref().
+ * @out_obj_old: if given, return the previously contained object. It only
+ * returns a object, if a matching entry was tracked previously, not if a
+ * new entry was created. Note that when passing @out_obj_old you obtain a reference
+ * to the boxed object and MUST return it with nm_dedup_multi_obj_unref().
*
* Adds and object to the index.
*
@@ -469,9 +447,8 @@ nm_dedup_multi_index_add_full (NMDedupMultiIndex *self,
const NMDedupMultiEntry *entry_order,
const NMDedupMultiEntry *entry_existing,
const NMDedupMultiHeadEntry *head_existing,
- const NMDedupMultiBox *box_existing,
const NMDedupMultiEntry **out_entry,
- const NMDedupMultiBox **out_old_box)
+ /* const NMDedupMultiObj ** */ gpointer out_obj_old)
{
NMDedupMultiEntry *entry;
@@ -498,8 +475,7 @@ nm_dedup_multi_index_add_full (NMDedupMultiIndex *self,
entry,
mode, entry_order,
(NMDedupMultiHeadEntry *) head_existing,
- box_existing,
- out_entry, out_old_box);
+ out_entry, out_obj_old);
}
/*****************************************************************************/
@@ -509,19 +485,19 @@ _remove_entry (NMDedupMultiIndex *self,
NMDedupMultiEntry *entry,
gboolean *out_head_entry_removed)
{
- Box *box;
+ const NMDedupMultiObj *obj;
NMDedupMultiHeadEntry *head_entry;
NMDedupMultiIdxType *idx_type;
nm_assert (self);
nm_assert (entry);
- nm_assert (entry->box);
+ nm_assert (entry->obj);
nm_assert (entry->head);
nm_assert (!c_list_is_empty (&entry->lst_entries));
nm_assert (g_hash_table_lookup (self->idx_entries, entry) == entry);
head_entry = (NMDedupMultiHeadEntry *) entry->head;
- box = (Box *) entry->box;
+ obj = entry->obj;
nm_assert (head_entry);
nm_assert (head_entry->len > 0);
@@ -555,7 +531,7 @@ _remove_entry (NMDedupMultiIndex *self,
g_slice_free (NMDedupMultiHeadEntry, head_entry);
}
- _box_unref (self, box);
+ nm_dedup_multi_obj_unref (obj);
}
static guint
@@ -791,20 +767,16 @@ nm_dedup_multi_index_dirty_remove_idx (NMDedupMultiIndex *self,
/*****************************************************************************/
static guint
-_dict_idx_box_hash (const Box *box)
+_dict_idx_objs_hash (const NMDedupMultiObj *obj)
{
- const NMDedupMultiObj *obj = box->parent.obj;
-
return obj->klass->obj_full_hash (obj);
}
static gboolean
-_dict_idx_box_equal (const Box *box_a,
- const Box *box_b)
+_dict_idx_objs_equal (const NMDedupMultiObj *obj_a,
+ const NMDedupMultiObj *obj_b)
{
const NMDedupMultiObjClass *klass;
- const NMDedupMultiObj *obj_a = box_a->parent.obj;
- const NMDedupMultiObj *obj_b = box_b->parent.obj;
klass = obj_a->klass;
@@ -824,105 +796,139 @@ _dict_idx_box_equal (const Box *box_a,
return klass->obj_full_equal (obj_a, obj_b);
}
-static void
-_box_unref (NMDedupMultiIndex *self,
- Box *box)
-{
- nm_assert (box);
- nm_assert (box->ref_count > 0);
- nm_assert (g_hash_table_lookup (self->idx_box, box) == box);
-
- if (--box->ref_count > 0)
- return;
-
- if (!g_hash_table_remove (self->idx_box, box))
- nm_assert_not_reached ();
-
- ((NMDedupMultiObj *) box->parent.obj)->klass->obj_put_ref ((NMDedupMultiObj *) box->parent.obj);
- g_slice_free (Box, box);
-}
-
-#define BOX_INIT(obj) \
- (&((const Box) { .parent = { .obj = obj, }, }))
-
-static Box *
-_box_find (NMDedupMultiIndex *index,
- /* const NMDedupMultiObj * */ gconstpointer obj)
+void
+nm_dedup_multi_index_obj_release (NMDedupMultiIndex *self,
+ /* const NMDedupMultiObj * */ gconstpointer obj)
{
- nm_assert (index);
+ nm_assert (self);
nm_assert (obj);
+ nm_assert (g_hash_table_lookup (self->idx_objs, obj) == obj);
+ nm_assert (((const NMDedupMultiObj *) obj)->_multi_idx == self);
- return g_hash_table_lookup (index->idx_box, BOX_INIT (obj));
+ ((NMDedupMultiObj *) obj)->_multi_idx = NULL;
+ if (!g_hash_table_remove (self->idx_objs, obj))
+ nm_assert_not_reached ();
}
-const NMDedupMultiBox *
-nm_dedup_multi_box_find (NMDedupMultiIndex *index,
- /* const NMDedupMultiObj * */ gconstpointer obj)
+gconstpointer
+nm_dedup_multi_index_obj_find (NMDedupMultiIndex *self,
+ /* const NMDedupMultiObj * */ gconstpointer obj)
{
- g_return_val_if_fail (index, NULL);
+ g_return_val_if_fail (self, NULL);
g_return_val_if_fail (obj, NULL);
- return (NMDedupMultiBox *) _box_find (index, obj);
+ return g_hash_table_lookup (self->idx_objs, obj);
}
-const NMDedupMultiBox *
-nm_dedup_multi_box_new (NMDedupMultiIndex *index,
- /* const NMDedupMultiObj * */ gconstpointer obj)
+gconstpointer
+nm_dedup_multi_index_obj_intern (NMDedupMultiIndex *self,
+ /* const NMDedupMultiObj * */ gconstpointer obj)
{
- Box *box;
- const NMDedupMultiObj *o;
+ const NMDedupMultiObj *obj_new = obj;
+ const NMDedupMultiObj *obj_old;
- g_return_val_if_fail (index, NULL);
- g_return_val_if_fail (obj, NULL);
+ nm_assert (self);
+ nm_assert (obj_new);
- box = _box_find (index, obj);
- if (box) {
- box->ref_count++;
- return (NMDedupMultiBox *) box;
+ if (obj_new->_multi_idx == self) {
+ nm_assert (g_hash_table_lookup (self->idx_objs, obj_new) == obj_new);
+ nm_dedup_multi_obj_ref (obj_new);
+ return obj_new;
}
- o = ((const NMDedupMultiObj *) obj)->klass->obj_get_ref (obj);
- if (!o)
- g_return_val_if_reached (NULL);
+ obj_old = g_hash_table_lookup (self->idx_objs, obj_new);
+ nm_assert (obj_old != obj_new);
+
+ if (obj_old) {
+ nm_assert (obj_old->_multi_idx == self);
+ nm_dedup_multi_obj_ref (obj_old);
+ return obj_old;
+ }
- box = g_slice_new (Box);
- box->parent.obj = o;
- box->ref_count = 1;
+ if (nm_dedup_multi_obj_needs_clone (obj_new))
+ obj_new = nm_dedup_multi_obj_clone (obj_new);
+ else
+ obj_new = nm_dedup_multi_obj_ref (obj_new);
- nm_assert (_dict_idx_box_equal (box, BOX_INIT (obj)));
- nm_assert (_dict_idx_box_equal (BOX_INIT (obj), box));
- nm_assert (_dict_idx_box_hash (BOX_INIT (obj)) == _dict_idx_box_hash (box));
+ nm_assert (obj_new);
+ nm_assert (!obj_new->_multi_idx);
- if (!nm_g_hash_table_add (index->idx_box, box))
+ if (!nm_g_hash_table_add (self->idx_objs, (gpointer) obj_new))
nm_assert_not_reached ();
- return &box->parent;
+ ((NMDedupMultiObj *) obj_new)->_multi_idx = self;
+ return obj_new;
}
-const NMDedupMultiBox *
-nm_dedup_multi_box_ref (const NMDedupMultiBox *box)
+const NMDedupMultiObj *
+nm_dedup_multi_obj_ref (const NMDedupMultiObj *obj)
{
- Box *b;
+ /* ref and unref accept const pointers. Objects is supposed to be shared
+ * and kept immutable. Disallowing to take/retrun a reference to a const
+ * NMPObject is cumbersome, because callers are precisely expected to
+ * keep a ref on the otherwise immutable object. */
- b = (Box *) box;
+ nm_assert (obj);
+ nm_assert (obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
+ nm_assert (obj->_ref_count > 0);
+
+ ((NMDedupMultiObj *) obj)->_ref_count++;
+ return obj;
+}
+
+const NMDedupMultiObj *
+nm_dedup_multi_obj_unref (const NMDedupMultiObj *obj)
+{
+ if (obj) {
+ nm_assert (obj->_ref_count > 0);
+ nm_assert (obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
+
+again:
+ if (--(((NMDedupMultiObj *) obj)->_ref_count) <= 0) {
+ if (obj->_multi_idx) {
+ /* restore the ref-count to 1 and release the object first
+ * from the index. Then, retry again to unref. */
+ ((NMDedupMultiObj *) obj)->_ref_count++;
+ nm_dedup_multi_index_obj_release (obj->_multi_idx, obj);
+ nm_assert (obj->_ref_count == 1);
+ nm_assert (!obj->_multi_idx);
+ goto again;
+ }
- g_return_val_if_fail (b, NULL);
- g_return_val_if_fail (b->ref_count > 0, NULL);
+ obj->klass->obj_destroy ((NMDedupMultiObj *) obj);
+ }
+ }
- b->ref_count++;
- return box;
+ return NULL;
}
-const NMDedupMultiBox *
-nm_dedup_multi_box_unref (NMDedupMultiIndex *self,
- const NMDedupMultiBox *box)
+gboolean
+nm_dedup_multi_obj_needs_clone (const NMDedupMultiObj *obj)
{
- g_return_val_if_fail (self, NULL);
- g_return_val_if_fail (box, NULL);
- g_return_val_if_fail (((Box *) box)->ref_count > 0, NULL);
+ nm_assert (obj);
- _box_unref (self, (Box *) box);
- return NULL;
+ if ( obj->_multi_idx
+ || obj->_ref_count == NM_OBJ_REF_COUNT_STACKINIT)
+ return TRUE;
+
+ if ( obj->klass->obj_needs_clone
+ && obj->klass->obj_needs_clone (obj))
+ return TRUE;
+
+ return FALSE;
+}
+
+const NMDedupMultiObj *
+nm_dedup_multi_obj_clone (const NMDedupMultiObj *obj)
+{
+ const NMDedupMultiObj *o;
+
+ nm_assert (obj);
+
+ o = obj->klass->obj_clone (obj);
+ nm_assert (o);
+ nm_assert (o->_ref_count == 1);
+ return o;
}
/*****************************************************************************/
@@ -935,7 +941,7 @@ nm_dedup_multi_index_new (void)
self = g_slice_new0 (NMDedupMultiIndex);
self->ref_count = 1;
self->idx_entries = g_hash_table_new ((GHashFunc) _dict_idx_entries_hash, (GEqualFunc) _dict_idx_entries_equal);
- self->idx_box = g_hash_table_new ((GHashFunc) _dict_idx_box_hash, (GEqualFunc) _dict_idx_box_equal);
+ self->idx_objs = g_hash_table_new ((GHashFunc) _dict_idx_objs_hash, (GEqualFunc) _dict_idx_objs_equal);
return self;
}
@@ -955,6 +961,7 @@ nm_dedup_multi_index_unref (NMDedupMultiIndex *self)
GHashTableIter iter;
const NMDedupMultiIdxType *idx_type;
NMDedupMultiEntry *entry;
+ const NMDedupMultiObj *obj;
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (self->ref_count > 0, NULL);
@@ -975,13 +982,15 @@ more:
nm_assert (g_hash_table_size (self->idx_entries) == 0);
- /* If callers took references to NMDedupMultiBox instances, they
- * must keep NMDedupMultiIndex alive for as long as they keep
- * the boxed reference. */
- nm_assert (g_hash_table_size (self->idx_box) == 0);
+ g_hash_table_iter_init (&iter, self->idx_objs);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &obj, NULL)) {
+ nm_assert (obj->_multi_idx == self);
+ ((NMDedupMultiObj * )obj)->_multi_idx = NULL;
+ }
+ g_hash_table_remove_all (self->idx_objs);
g_hash_table_unref (self->idx_entries);
- g_hash_table_unref (self->idx_box);
+ g_hash_table_unref (self->idx_objs);
g_slice_free (NMDedupMultiIndex, self);
return NULL;
diff --git a/shared/nm-utils/nm-dedup-multi.h b/shared/nm-utils/nm-dedup-multi.h
index fc4283a808..090cc743a0 100644
--- a/shared/nm-utils/nm-dedup-multi.h
+++ b/shared/nm-utils/nm-dedup-multi.h
@@ -29,7 +29,6 @@
typedef struct _NMDedupMultiObj NMDedupMultiObj;
typedef struct _NMDedupMultiObjClass NMDedupMultiObjClass;
-typedef struct _NMDedupMultiBox NMDedupMultiBox;
typedef struct _NMDedupMultiIdxType NMDedupMultiIdxType;
typedef struct _NMDedupMultiIdxTypeClass NMDedupMultiIdxTypeClass;
typedef struct _NMDedupMultiEntry NMDedupMultiEntry;
@@ -57,16 +56,18 @@ struct _NMDedupMultiObj {
NMObjBaseInst parent;
const NMDedupMultiObjClass *klass;
};
+ NMDedupMultiIndex *_multi_idx;
+ guint _ref_count;
};
struct _NMDedupMultiObjClass {
NMObjBaseClass parent;
- /* obj_get_ref() may just increase the ref-count, or it may allocate a new object.
- * In any case, it returns ownership of an equal object to @obj. */
- NMDedupMultiObj *(*obj_get_ref) (const NMDedupMultiObj *obj);
+ const NMDedupMultiObj *(*obj_clone) (const NMDedupMultiObj *obj);
- void (*obj_put_ref) (NMDedupMultiObj *obj);
+ gboolean (*obj_needs_clone) (const NMDedupMultiObj *obj);
+
+ void (*obj_destroy) (NMDedupMultiObj *obj);
gboolean obj_full_equality_allows_different_class;
@@ -79,14 +80,19 @@ struct _NMDedupMultiObjClass {
/*****************************************************************************/
-struct _NMDedupMultiBox {
- gconstpointer obj;
-};
+const NMDedupMultiObj *nm_dedup_multi_obj_ref (const NMDedupMultiObj *obj);
+const NMDedupMultiObj *nm_dedup_multi_obj_unref (const NMDedupMultiObj *obj);
+const NMDedupMultiObj *nm_dedup_multi_obj_clone (const NMDedupMultiObj *obj);
+gboolean nm_dedup_multi_obj_needs_clone (const NMDedupMultiObj *obj);
+
+gconstpointer nm_dedup_multi_index_obj_intern (NMDedupMultiIndex *self,
+ /* const NMDedupMultiObj * */ gconstpointer obj);
-const NMDedupMultiBox *nm_dedup_multi_box_new (NMDedupMultiIndex *index, /* const NMDedupMultiObj * */ gconstpointer obj);
-const NMDedupMultiBox *nm_dedup_multi_box_find (NMDedupMultiIndex *index, /* const NMDedupMultiObj * */ gconstpointer obj);
-const NMDedupMultiBox *nm_dedup_multi_box_ref (const NMDedupMultiBox *box);
-const NMDedupMultiBox *nm_dedup_multi_box_unref (NMDedupMultiIndex *index, const NMDedupMultiBox *box);
+void nm_dedup_multi_index_obj_release (NMDedupMultiIndex *self,
+ /* const NMDedupMultiObj * */ gconstpointer obj);
+
+/* const NMDedupMultiObj * */ gconstpointer nm_dedup_multi_index_obj_find (NMDedupMultiIndex *self,
+ /* const NMDedupMultiObj * */ gconstpointer obj);
/*****************************************************************************/
@@ -190,12 +196,7 @@ struct _NMDedupMultiEntry {
* All entries compare equal according to idx_obj_partition_equal(). */
CList lst_entries;
- /* the object instance. It is ref-counted and shared.
- * Note that this instance must be immutable once it
- * is added to the list.
- *
- * For head entries, @box is NULL and @head points to itself. */
- const NMDedupMultiBox *box;
+ /* const NMDedupMultiObj * */ gconstpointer obj;
bool is_head;
bool dirty;
@@ -255,16 +256,15 @@ gboolean nm_dedup_multi_index_add_full (NMDedupMultiIndex *self,
const NMDedupMultiEntry *entry_order,
const NMDedupMultiEntry *entry_existing,
const NMDedupMultiHeadEntry *head_existing,
- const NMDedupMultiBox *box_existing,
const NMDedupMultiEntry **out_entry,
- const NMDedupMultiBox **out_old_box);
+ /* const NMDedupMultiObj ** */ gpointer out_obj_old);
gboolean nm_dedup_multi_index_add (NMDedupMultiIndex *self,
NMDedupMultiIdxType *idx_type,
/*const NMDedupMultiObj * */ gconstpointer obj,
NMDedupMultiIdxMode mode,
const NMDedupMultiEntry **out_entry,
- const NMDedupMultiBox **out_old_box);
+ /* const NMDedupMultiObj ** */ gpointer out_obj_old);
const NMDedupMultiEntry *nm_dedup_multi_index_lookup_obj (NMDedupMultiIndex *self,
const NMDedupMultiIdxType *idx_type,
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 50000e6275..eca46085ad 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -215,7 +215,7 @@ static const NMPlatformIP4Route *
_entry_iter_get_ip4_route (const CList *iter)
{
const NMDedupMultiEntry *e = c_list_entry (iter, NMDedupMultiEntry, lst_entries);
- const NMPObject *o = (NMPObject *) e->box->obj;
+ const NMPObject *o = e->obj;
nm_assert (o);
nm_assert (NMP_OBJECT_GET_TYPE (o) == NMP_OBJECT_TYPE_IP4_ROUTE);
@@ -236,8 +236,8 @@ nm_ip4_config_iter_ip4_route_next (NMDedupMultiIter *ipconf_iter, const NMPlatfo
has_next = nm_dedup_multi_iter_next (ipconf_iter);
if (has_next) {
- nm_assert (NMP_OBJECT_GET_TYPE (ipconf_iter->current->box->obj) == NMP_OBJECT_TYPE_IP4_ROUTE);
- NM_SET_OUT (out_route, &(((const NMPObject *) ipconf_iter->current->box->obj)->ip4_route));
+ nm_assert (NMP_OBJECT_GET_TYPE (ipconf_iter->current->obj) == NMP_OBJECT_TYPE_IP4_ROUTE);
+ NM_SET_OUT (out_route, &(((const NMPObject *) ipconf_iter->current->obj)->ip4_route));
}
return has_next;
}
@@ -1779,7 +1779,7 @@ _add_route (NMIP4Config *config, const NMPObject *o_new, const NMPlatformIP4Rout
{
NMIP4ConfigPrivate *priv;
NMPObject o_new_storage;
- const NMDedupMultiBox *box_old;
+ nm_auto_nmpobj const NMPObject *obj_old = NULL;
nm_assert (NM_IS_IP4_CONFIG (config));
@@ -1812,16 +1812,13 @@ _add_route (NMIP4Config *config, const NMPObject *o_new, const NMPlatformIP4Rout
o_new,
NM_DEDUP_MULTI_IDX_MODE_APPEND,
NULL,
- &box_old)) {
- if (box_old)
- nm_dedup_multi_box_unref (priv->multi_idx, box_old);
+ &obj_old))
return;
- }
- if (box_old) {
+ if (obj_old) {
NMIPConfigSource old_source;
- old_source = ((const NMPObject *) box_old->obj)->ip_route.rt_source;
+ old_source = obj_old->ip_route.rt_source;
/* we want to keep the maximum rt_source. But since we expect
* that usually we already add the maxiumum right away, we first try to
* add the new route (replacing the old one). Only if we later
@@ -1842,7 +1839,6 @@ _add_route (NMIP4Config *config, const NMPObject *o_new, const NMPlatformIP4Rout
NULL))
nm_assert_not_reached ();
}
- nm_dedup_multi_box_unref (priv->multi_idx, box_old);
}
_notify (config, PROP_ROUTE_DATA);
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 65dc6e0168..f4cd591771 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -3295,7 +3295,7 @@ cache_prune_one_type (NMPlatform *platform, NMPObjectType obj_type)
if (iter.current->dirty) {
nm_auto_nmpobj const NMPObject *obj_old = NULL;
- obj = iter.current->box->obj;
+ obj = iter.current->obj;
_LOGt ("cache-prune: prune %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
cache_op = nmp_cache_remove (cache, obj, TRUE, &obj_old);
nm_assert (cache_op == NMP_CACHE_OPS_REMOVED);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index e310d26363..dd3445e2f8 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -491,38 +491,6 @@ nmp_class_from_type (NMPObjectType obj_type)
/*****************************************************************************/
-const NMPObject *
-nmp_object_ref (const NMPObject *obj)
-{
- /* ref and unref accept const pointers. NMPObject is supposed to be shared
- * and kept immutable. Disallowing to take/retrun a reference to a const
- * NMPObject is cumbersome, because callers are precisely expected to
- * keep a ref on the otherwise immutable object. */
- g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj), NULL);
- g_return_val_if_fail (obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT, NULL);
- ((NMPObject *) obj)->_ref_count++;
-
- return obj;
-}
-
-void
-nmp_object_unref (const NMPObject *obj)
-{
- if (obj) {
- NMPObject *o = (NMPObject *) obj;
-
- g_return_if_fail (o->_ref_count > 0);
- g_return_if_fail (o->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
- if (--o->_ref_count <= 0) {
- const NMPClass *klass = o->_class;
-
- if (klass->cmd_obj_dispose)
- klass->cmd_obj_dispose (o);
- g_slice_free1 (klass->sizeof_data + G_STRUCT_OFFSET (NMPObject, object), o);
- }
- }
-}
-
static void
_vt_cmd_obj_dispose_link (NMPObject *obj)
{
@@ -551,7 +519,7 @@ _nmp_object_new_from_class (const NMPClass *klass)
obj = g_slice_alloc0 (klass->sizeof_data + G_STRUCT_OFFSET (NMPObject, object));
obj->_class = klass;
- obj->_ref_count = 1;
+ obj->parent._ref_count = 1;
return obj;
}
@@ -587,7 +555,7 @@ _nmp_object_stackinit_from_class (NMPObject *obj, const NMPClass *klass)
memset (obj, 0, sizeof (NMPObject));
obj->_class = klass;
- obj->_ref_count = NM_OBJ_REF_COUNT_STACKINIT;
+ obj->parent._ref_count = NM_OBJ_REF_COUNT_STACKINIT;
}
static NMPObject *
@@ -601,7 +569,7 @@ _nmp_object_stackinit_from_type (NMPObject *obj, NMPObjectType obj_type)
memset (obj, 0, sizeof (NMPObject));
obj->_class = klass;
- obj->_ref_count = NM_OBJ_REF_COUNT_STACKINIT;
+ obj->parent._ref_count = NM_OBJ_REF_COUNT_STACKINIT;
return obj;
}
@@ -742,7 +710,7 @@ nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode
case NMP_OBJECT_TO_STRING_ALL:
g_snprintf (buf, buf_size,
"[%s,%p,%u,%calive,%cvisible; %s]",
- klass->obj_type_name, obj, obj->_ref_count,
+ klass->obj_type_name, obj, obj->parent._ref_count,
nmp_object_is_alive (obj) ? '+' : '-',
nmp_object_is_visible (obj) ? '+' : '-',
NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf2, sizeof (buf2)));
@@ -768,7 +736,7 @@ _vt_cmd_obj_to_string_link (const NMPObject *obj, NMPObjectToStringMode to_strin
case NMP_OBJECT_TO_STRING_ALL:
g_snprintf (buf, buf_size,
"[%s,%p,%u,%calive,%cvisible,%cin-nl,%p; %s]",
- klass->obj_type_name, obj, obj->_ref_count,
+ klass->obj_type_name, obj, obj->parent._ref_count,
nmp_object_is_alive (obj) ? '+' : '-',
nmp_object_is_visible (obj) ? '+' : '-',
obj->_link.netlink.is_in_netlink ? '+' : '-',
@@ -808,7 +776,7 @@ _vt_cmd_obj_to_string_lnk_vlan (const NMPObject *obj, NMPObjectToStringMode to_s
g_snprintf (buf, buf_size,
"[%s,%p,%u,%calive,%cvisible; %s]",
- klass->obj_type_name, obj, obj->_ref_count,
+ klass->obj_type_name, obj, obj->parent._ref_count,
nmp_object_is_alive (obj) ? '+' : '-',
nmp_object_is_visible (obj) ? '+' : '-',
nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof (buf2)));
@@ -1339,22 +1307,25 @@ static const guint8 _supported_cache_ids_ipx_route[] = {
/*****************************************************************************/
-static NMDedupMultiObj *
-_vt_dedup_obj_get_ref (const NMDedupMultiObj *obj)
+static void
+_vt_dedup_obj_destroy (NMDedupMultiObj *obj)
{
NMPObject *o = (NMPObject *) obj;
+ const NMPClass *klass;
- if (NMP_OBJECT_IS_STACKINIT (o)) {
- return (NMDedupMultiObj *) nmp_object_new (NMP_OBJECT_GET_TYPE (o),
- &o->object);
- }
- return (NMDedupMultiObj *) nmp_object_ref (o);
+ nm_assert (o->parent._ref_count == 0);
+ nm_assert (!o->parent._multi_idx);
+
+ klass = o->_class;
+ if (klass->cmd_obj_dispose)
+ klass->cmd_obj_dispose (o);
+ g_slice_free1 (klass->sizeof_data + G_STRUCT_OFFSET (NMPObject, object), o);
}
-static void
-_vt_dedup_obj_put_ref (NMDedupMultiObj *obj)
+static const NMDedupMultiObj *
+_vt_dedup_obj_clone (const NMDedupMultiObj *obj)
{
- nmp_object_unref ((NMPObject *) obj);
+ return (const NMDedupMultiObj *) nmp_object_clone ((const NMPObject *) obj, FALSE);
}
static guint
@@ -1373,8 +1344,8 @@ _vt_dedup_obj_full_equal (const NMDedupMultiObj *obj_a,
#define DEDUP_MULTI_OBJ_CLASS_INIT() \
{ \
- .obj_get_ref = _vt_dedup_obj_get_ref, \
- .obj_put_ref = _vt_dedup_obj_put_ref, \
+ .obj_clone = _vt_dedup_obj_clone, \
+ .obj_destroy = _vt_dedup_obj_destroy, \
.obj_full_hash = _vt_dedup_obj_full_hash, \
.obj_full_equal = _vt_dedup_obj_full_equal, \
}
@@ -1512,12 +1483,18 @@ nmp_cache_link_connected_needs_toggle_by_ifindex (const NMPCache *cache, int mas
static const NMDedupMultiEntry *
_lookup_obj (const NMPCache *cache, const NMPObject *obj)
{
+ const NMDedupMultiEntry *entry;
+
nm_assert (cache);
nm_assert (NMP_OBJECT_IS_VALID (obj));
- return nm_dedup_multi_index_lookup_obj (cache->multi_idx,
- _idx_type_get (cache, NMP_CACHE_ID_TYPE_OBJECT_TYPE),
- obj);
+ entry = nm_dedup_multi_index_lookup_obj (cache->multi_idx,
+ _idx_type_get (cache, NMP_CACHE_ID_TYPE_OBJECT_TYPE),
+ obj);
+ nm_assert (!entry
+ || ( NMP_OBJECT_IS_VALID (entry->obj)
+ && NMP_OBJECT_GET_CLASS (entry->obj) == NMP_OBJECT_GET_CLASS (obj)));
+ return entry;
}
const NMPObject *
@@ -1529,7 +1506,7 @@ nmp_cache_lookup_obj (const NMPCache *cache, const NMPObject *obj)
g_return_val_if_fail (obj, NULL);
entry = _lookup_obj (cache, obj);
- return entry ? entry->box->obj : NULL;
+ return entry ? entry->obj : NULL;
}
const NMDedupMultiEntry *
@@ -1883,33 +1860,29 @@ nmp_cache_lookup_link_full (const NMPCache *cache,
static void
_idxcache_update_box_move (NMPCache *cache,
NMPCacheIdType cache_id_type,
- const NMDedupMultiBox *box_old,
- const NMDedupMultiBox *box_new)
+ const NMPObject *obj_old,
+ const NMPObject *obj_new)
{
const NMDedupMultiEntry *entry_new;
const NMDedupMultiEntry *entry_old;
const NMDedupMultiEntry *entry_order;
NMDedupMultiIdxType *idx_type;
- const NMPObject *new, *old;
-
- new = box_new ? box_new->obj : NULL;
- old = box_old ? box_old->obj : NULL;
- nm_assert (new || old);
- nm_assert (!new || NMP_OBJECT_GET_TYPE (new) != NMP_OBJECT_TYPE_UNKNOWN);
- nm_assert (!old || NMP_OBJECT_GET_TYPE (old) != NMP_OBJECT_TYPE_UNKNOWN);
- nm_assert (!old || !new || NMP_OBJECT_GET_CLASS (new) == NMP_OBJECT_GET_CLASS (old));
- nm_assert (!old || !new || !nmp_object_equal (new, old));
- nm_assert (!box_new || box_new == nm_dedup_multi_box_find (cache->multi_idx, new));
- nm_assert (!box_old || box_old == nm_dedup_multi_box_find (cache->multi_idx, old));
+ nm_assert (obj_new || obj_old);
+ nm_assert (!obj_new || NMP_OBJECT_GET_TYPE (obj_new) != NMP_OBJECT_TYPE_UNKNOWN);
+ nm_assert (!obj_old || NMP_OBJECT_GET_TYPE (obj_old) != NMP_OBJECT_TYPE_UNKNOWN);
+ nm_assert (!obj_old || !obj_new || NMP_OBJECT_GET_CLASS (obj_new) == NMP_OBJECT_GET_CLASS (obj_old));
+ nm_assert (!obj_old || !obj_new || !nmp_object_equal (obj_new, obj_old));
+ nm_assert (!obj_new || obj_new == nm_dedup_multi_index_obj_find (cache->multi_idx, obj_new));
+ nm_assert (!obj_old || obj_old == nm_dedup_multi_index_obj_find (cache->multi_idx, obj_old));
idx_type = _idx_type_get (cache, cache_id_type);
- if (old) {
+ if (obj_old) {
entry_old = nm_dedup_multi_index_lookup_obj (cache->multi_idx,
idx_type,
- old);
- if (!new) {
+ obj_old);
+ if (!obj_new) {
if (entry_old)
nm_dedup_multi_index_remove_entry (cache->multi_idx, entry_old);
return;
@@ -1917,34 +1890,33 @@ _idxcache_update_box_move (NMPCache *cache,
} else
entry_old = NULL;
- if (new) {
- if ( old
- && nm_dedup_multi_idx_type_id_equal (idx_type, old, new)
- && nm_dedup_multi_idx_type_partition_equal (idx_type, old, new)) {
- /* optimize. We just looked up the @old entry and @new compares equal
+ if (obj_new) {
+ if ( obj_old
+ && nm_dedup_multi_idx_type_id_equal (idx_type, obj_old, obj_new)
+ && nm_dedup_multi_idx_type_partition_equal (idx_type, obj_old, obj_new)) {
+ /* optimize. We just looked up the @obj_old entry and @obj_new compares equal
* according to idx_obj_id_equal(). entry_new is the same as entry_old. */
entry_new = entry_old;
} else {
entry_new = nm_dedup_multi_index_lookup_obj (cache->multi_idx,
idx_type,
- new);
+ obj_new);
}
if (entry_new)
entry_order = entry_new;
else if ( entry_old
- && nm_dedup_multi_idx_type_partition_equal (idx_type, entry_old->box->obj, new))
+ && nm_dedup_multi_idx_type_partition_equal (idx_type, entry_old->obj, obj_new))
entry_order = entry_old;
else
entry_order = NULL;
nm_dedup_multi_index_add_full (cache->multi_idx,
idx_type,
- new,
+ obj_new,
NM_DEDUP_MULTI_IDX_MODE_APPEND,
entry_order,
entry_new ?: NM_DEDUP_MULTI_ENTRY_MISSING,
entry_new ? entry_new->head : (entry_order ? entry_order->head : NULL),
- box_new,
&entry_new,
NULL);
@@ -1952,8 +1924,8 @@ _idxcache_update_box_move (NMPCache *cache,
if (entry_new) {
nm_assert (idx_type->klass->idx_obj_partitionable);
nm_assert (idx_type->klass->idx_obj_partition_equal);
- nm_assert (idx_type->klass->idx_obj_partitionable (idx_type, entry_new->box->obj));
- nm_assert (idx_type->klass->idx_obj_partition_equal (idx_type, (gpointer) new, entry_new->box->obj));
+ nm_assert (idx_type->klass->idx_obj_partitionable (idx_type, entry_new->obj));
+ nm_assert (idx_type->klass->idx_obj_partition_equal (idx_type, (gpointer) obj_new, entry_new->obj));
}
#endif
} else
@@ -1974,8 +1946,7 @@ _idxcache_update (NMPCache *cache,
const guint8 *i_idx_type;
NMDedupMultiIdxType *idx_type_o = _idx_type_get (cache, NMP_CACHE_ID_TYPE_OBJECT_TYPE);
const NMDedupMultiEntry *entry_new = NULL;
- const NMDedupMultiBox *box_old;
- const NMDedupMultiBox *box_old2 = NULL;
+ nm_auto_nmpobj const NMPObject *obj_old = NULL;
/* we update an object in the cache.
*
@@ -1985,22 +1956,23 @@ _idxcache_update (NMPCache *cache,
nm_assert (cache);
nm_assert (entry_old || obj_new);
nm_assert (!obj_new || nmp_object_is_alive (obj_new));
- nm_assert (!entry_old || entry_old == nm_dedup_multi_index_lookup_obj (cache->multi_idx, idx_type_o, entry_old->box->obj));
+ nm_assert (!entry_old || entry_old == nm_dedup_multi_index_lookup_obj (cache->multi_idx, idx_type_o, entry_old->obj));
nm_assert (!obj_new || entry_old == nm_dedup_multi_index_lookup_obj (cache->multi_idx, idx_type_o, obj_new));
nm_assert (!entry_old || entry_old->head->idx_type == idx_type_o);
nm_assert ( !entry_old
|| !obj_new
- || nm_dedup_multi_idx_type_partition_equal (idx_type_o, entry_old->box->obj, obj_new));
+ || nm_dedup_multi_idx_type_partition_equal (idx_type_o, entry_old->obj, obj_new));
nm_assert ( !entry_old
|| !obj_new
- || nm_dedup_multi_idx_type_id_equal (idx_type_o, entry_old->box->obj, obj_new));
+ || nm_dedup_multi_idx_type_id_equal (idx_type_o, entry_old->obj, obj_new));
nm_assert ( !entry_old
|| !obj_new
- || ( obj_new->parent.klass == ((const NMPObject *) entry_old->box->obj)->parent.klass
- && !obj_new->parent.klass->obj_full_equal ((NMDedupMultiObj *) obj_new, entry_old->box->obj)));
+ || ( obj_new->parent.klass == ((const NMPObject *) entry_old->obj)->parent.klass
+ && !obj_new->parent.klass->obj_full_equal ((NMDedupMultiObj *) obj_new, entry_old->obj)));
- /* keep a boxed reference to the pre-existing entry */
- box_old = entry_old ? nm_dedup_multi_box_ref (entry_old->box) : NULL;
+ /* keep a reference to the pre-existing entry */
+ if (entry_old)
+ obj_old = nmp_object_ref (entry_old->obj);
/* first update the main index NMP_CACHE_ID_TYPE_OBJECT_TYPE.
* We already know the pre-existing @entry old, so all that
@@ -2009,6 +1981,8 @@ _idxcache_update (NMPCache *cache,
*
* We also get the new boxed object, which we need below. */
if (obj_new) {
+ nm_auto_nmpobj NMPObject *obj_old2 = NULL;
+
nm_dedup_multi_index_add_full (cache->multi_idx,
idx_type_o,
obj_new,
@@ -2016,34 +1990,28 @@ _idxcache_update (NMPCache *cache,
NULL,
entry_old ?: NM_DEDUP_MULTI_ENTRY_MISSING,
NULL,
- NULL,
&entry_new,
- &box_old2);
+ (const NMDedupMultiObj **) &obj_old2);
nm_assert (entry_new);
- nm_assert (box_old == box_old2);
+ nm_assert (obj_old == obj_old2);
nm_assert (!entry_old || entry_old == entry_new);
- if (box_old2)
- nm_dedup_multi_box_unref (cache->multi_idx, box_old2);
} else
nm_dedup_multi_index_remove_entry (cache->multi_idx, entry_old);
/* now update all other indexes. We know the previously boxed entry, and the
* newly boxed one. */
- klass = NMP_OBJECT_GET_CLASS (entry_new ? entry_new->box->obj : box_old->obj);
+ klass = NMP_OBJECT_GET_CLASS (entry_new ? entry_new->obj : obj_old);
for (i_idx_type = klass->supported_cache_ids; *i_idx_type; i_idx_type++) {
NMPCacheIdType id_type = *i_idx_type;
if (id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE)
continue;
_idxcache_update_box_move (cache, id_type,
- box_old,
- entry_new ? entry_new->box : NULL);
+ obj_old,
+ entry_new ? entry_new->obj : NULL);
}
NM_SET_OUT (out_entry_new, entry_new);
-
- if (box_old)
- nm_dedup_multi_box_unref (cache->multi_idx, box_old);
}
NMPCacheOpsType
@@ -2062,7 +2030,7 @@ nmp_cache_remove (NMPCache *cache,
return NMP_CACHE_OPS_UNCHANGED;
}
- obj_old = entry_old->box->obj;
+ obj_old = entry_old->obj;
NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old));
@@ -2095,7 +2063,7 @@ nmp_cache_remove_netlink (NMPCache *cache,
return NMP_CACHE_OPS_UNCHANGED;
}
- obj_old = entry_old->box->obj;
+ obj_old = entry_old->obj;
if (NMP_OBJECT_GET_TYPE (obj_needle) == NMP_OBJECT_TYPE_LINK) {
/* For nmp_cache_remove_netlink() we have an incomplete @obj_needle instance to be
@@ -2128,7 +2096,7 @@ nmp_cache_remove_netlink (NMPCache *cache,
entry_old,
obj_new,
&entry_new);
- NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->box->obj));
+ NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj));
return NMP_CACHE_OPS_UPDATED;
}
@@ -2182,10 +2150,7 @@ nmp_cache_update_netlink (NMPCache *cache,
nm_assert (NMP_OBJECT_GET_TYPE (obj_hand_over) != NMP_OBJECT_TYPE_LINK ||
( !obj_hand_over->_link.udev.device
&& !obj_hand_over->link.driver));
- nm_assert (({
- const NMDedupMultiBox *_b = nm_dedup_multi_box_find (cache->multi_idx, obj_hand_over);
- !_b || obj_hand_over != _b->obj;
- }));
+ nm_assert (nm_dedup_multi_index_obj_find (cache->multi_idx, obj_hand_over) != obj_hand_over);
entry_old = _lookup_obj (cache, obj_hand_over);
@@ -2207,11 +2172,11 @@ nmp_cache_update_netlink (NMPCache *cache,
entry_old,
obj_hand_over,
&entry_new);
- NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->box->obj));
+ NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj));
return NMP_CACHE_OPS_ADDED;
}
- obj_old = entry_old->box->obj;
+ obj_old = entry_old->obj;
if (NMP_OBJECT_GET_TYPE (obj_hand_over) == NMP_OBJECT_TYPE_LINK) {
if (!obj_hand_over->_link.netlink.is_in_netlink) {
@@ -2244,6 +2209,13 @@ nmp_cache_update_netlink (NMPCache *cache,
udev_device_unref (obj_hand_over->_link.udev.device);
obj_hand_over->_link.udev.device = obj_old->_link.udev.device ? udev_device_ref (obj_old->_link.udev.device) : NULL;
_nmp_object_fixup_link_udev_fields (&obj_hand_over, NULL, cache->use_udev);
+
+ if (obj_hand_over->_link.netlink.lnk) {
+ nm_auto_nmpobj const NMPObject *lnk_old = obj_hand_over->_link.netlink.lnk;
+
+ /* let's dedup/intern the lnk object. */
+ obj_hand_over->_link.netlink.lnk = nm_dedup_multi_index_obj_intern (cache->multi_idx, lnk_old);
+ }
}
} else
is_alive = nmp_object_is_alive (obj_hand_over);
@@ -2267,7 +2239,7 @@ nmp_cache_update_netlink (NMPCache *cache,
entry_old,
obj_hand_over,
&entry_new);
- NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->box->obj));
+ NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj));
return NMP_CACHE_OPS_UPDATED;
}
@@ -2303,10 +2275,10 @@ nmp_cache_update_link_udev (NMPCache *cache,
obj_new,
&entry_new);
NM_SET_OUT (out_obj_old, NULL);
- NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->box->obj));
+ NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj));
return NMP_CACHE_OPS_ADDED;
} else {
- obj_old = entry_old->box->obj;
+ obj_old = entry_old->obj;
NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old));
if (obj_old->_link.udev.device == udevice) {
@@ -2332,7 +2304,7 @@ nmp_cache_update_link_udev (NMPCache *cache,
entry_old,
obj_new,
&entry_new);
- NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->box->obj));
+ NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj));
return NMP_CACHE_OPS_UPDATED;
}
}
@@ -2356,7 +2328,7 @@ nmp_cache_update_link_master_connected (NMPCache *cache,
return NMP_CACHE_OPS_UNCHANGED;
}
- obj_old = entry_old->box->obj;
+ obj_old = entry_old->obj;
if (!nmp_cache_link_connected_needs_toggle (cache, obj_old, NULL, NULL)) {
NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old));
@@ -2372,7 +2344,7 @@ nmp_cache_update_link_master_connected (NMPCache *cache,
entry_old,
obj_new,
&entry_new);
- NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->box->obj));
+ NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj));
return NMP_CACHE_OPS_UPDATED;
}
@@ -2542,6 +2514,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip6_route_cmp,
},
[NMP_OBJECT_TYPE_LNK_GRE - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_GRE,
.sizeof_data = sizeof (NMPObjectLnkGre),
.sizeof_public = sizeof (NMPlatformLnkGre),
@@ -2552,6 +2525,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp,
},
[NMP_OBJECT_TYPE_LNK_INFINIBAND - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_INFINIBAND,
.sizeof_data = sizeof (NMPObjectLnkInfiniband),
.sizeof_public = sizeof (NMPlatformLnkInfiniband),
@@ -2562,6 +2536,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_infiniband_cmp,
},
[NMP_OBJECT_TYPE_LNK_IP6TNL - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_IP6TNL,
.sizeof_data = sizeof (NMPObjectLnkIp6Tnl),
.sizeof_public = sizeof (NMPlatformLnkIp6Tnl),
@@ -2572,6 +2547,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp,
},
[NMP_OBJECT_TYPE_LNK_IPIP - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_IPIP,
.sizeof_data = sizeof (NMPObjectLnkIpIp),
.sizeof_public = sizeof (NMPlatformLnkIpIp),
@@ -2582,6 +2558,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ipip_cmp,
},
[NMP_OBJECT_TYPE_LNK_MACSEC - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_MACSEC,
.sizeof_data = sizeof (NMPObjectLnkMacsec),
.sizeof_public = sizeof (NMPlatformLnkMacsec),
@@ -2592,6 +2569,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macsec_cmp,
},
[NMP_OBJECT_TYPE_LNK_MACVLAN - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_MACVLAN,
.sizeof_data = sizeof (NMPObjectLnkMacvlan),
.sizeof_public = sizeof (NMPlatformLnkMacvlan),
@@ -2602,6 +2580,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macvlan_cmp,
},
[NMP_OBJECT_TYPE_LNK_MACVTAP - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_MACVTAP,
.sizeof_data = sizeof (NMPObjectLnkMacvtap),
.sizeof_public = sizeof (NMPlatformLnkMacvtap),
@@ -2612,6 +2591,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macvlan_cmp,
},
[NMP_OBJECT_TYPE_LNK_SIT - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_SIT,
.sizeof_data = sizeof (NMPObjectLnkSit),
.sizeof_public = sizeof (NMPlatformLnkSit),
@@ -2622,6 +2602,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_sit_cmp,
},
[NMP_OBJECT_TYPE_LNK_VLAN - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_VLAN,
.sizeof_data = sizeof (NMPObjectLnkVlan),
.sizeof_public = sizeof (NMPlatformLnkVlan),
@@ -2637,6 +2618,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vlan_cmp,
},
[NMP_OBJECT_TYPE_LNK_VXLAN - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_VXLAN,
.sizeof_data = sizeof (NMPObjectLnkVxlan),
.sizeof_public = sizeof (NMPlatformLnkVxlan),
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index 6c0098bfce..5574e0b3b6 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -144,7 +144,7 @@ typedef struct {
bool is_in_netlink;
/* Additional data that depends on the link-type (IFLA_INFO_DATA) */
- NMPObject *lnk;
+ const NMPObject *lnk;
} netlink;
struct {
@@ -232,7 +232,6 @@ struct _NMPObject {
NMDedupMultiObj parent;
const NMPClass *_class;
};
- guint _ref_count;
union {
NMPlatformObject object;
@@ -298,7 +297,7 @@ NMP_OBJECT_UP_CAST(const NMPlatformObject *plobj)
obj = plobj
? (NMPObject *) ( &(((char *) plobj)[-((int) G_STRUCT_OFFSET (NMPObject, object))]) )
: NULL;
- nm_assert (!obj || (obj->_ref_count > 0 && NMP_CLASS_IS_VALID (obj->_class)));
+ nm_assert (!obj || (obj->parent._ref_count > 0 && NMP_CLASS_IS_VALID (obj->_class)));
return obj;
}
#define NMP_OBJECT_UP_CAST(plobj) (NMP_OBJECT_UP_CAST ((const NMPlatformObject *) (plobj)))
@@ -307,7 +306,7 @@ static inline gboolean
NMP_OBJECT_IS_VALID (const NMPObject *obj)
{
nm_assert (!obj || ( obj
- && obj->_ref_count > 0
+ && obj->parent._ref_count > 0
&& NMP_CLASS_IS_VALID (obj->_class)));
/* There isn't really much to check. Either @obj is NULL, or we must
@@ -320,7 +319,7 @@ NMP_OBJECT_IS_STACKINIT (const NMPObject *obj)
{
nm_assert (!obj || NMP_OBJECT_IS_VALID (obj));
- return obj && obj->_ref_count == NM_OBJ_REF_COUNT_STACKINIT;
+ return obj && obj->parent._ref_count == NM_OBJ_REF_COUNT_STACKINIT;
}
static inline const NMPClass *
@@ -377,8 +376,26 @@ NMP_OBJECT_GET_TYPE (const NMPObject *obj)
const NMPClass *nmp_class_from_type (NMPObjectType obj_type);
-const NMPObject *nmp_object_ref (const NMPObject *object);
-void nmp_object_unref (const NMPObject *object);
+static inline const NMPObject *
+nmp_object_ref (const NMPObject *obj)
+{
+ /* ref and unref accept const pointers. NMPObject is supposed to be shared
+ * and kept immutable. Disallowing to take/retrun a reference to a const
+ * NMPObject is cumbersome, because callers are precisely expected to
+ * keep a ref on the otherwise immutable object. */
+ g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj), NULL);
+ g_return_val_if_fail (obj->parent._ref_count != NM_OBJ_REF_COUNT_STACKINIT, NULL);
+
+ return (const NMPObject *) nm_dedup_multi_obj_ref ((const NMDedupMultiObj *) obj);
+}
+
+static inline const NMPObject *
+nmp_object_unref (const NMPObject *obj)
+{
+ nm_dedup_multi_obj_unref ((const NMDedupMultiObj *) obj);
+ return NULL;
+}
+
NMPObject *nmp_object_new (NMPObjectType obj_type, const NMPlatformObject *plob);
NMPObject *nmp_object_new_link (int ifindex);
@@ -470,8 +487,8 @@ nmp_cache_iter_next (NMDedupMultiIter *iter, const NMPObject **out_obj)
has_next = nm_dedup_multi_iter_next (iter);
if (has_next) {
- nm_assert (NMP_OBJECT_IS_VALID (iter->current->box->obj));
- NM_SET_OUT (out_obj, iter->current->box->obj);
+ nm_assert (NMP_OBJECT_IS_VALID (iter->current->obj));
+ NM_SET_OUT (out_obj, iter->current->obj);
}
return has_next;
}
@@ -483,8 +500,8 @@ nmp_cache_iter_next_link (NMDedupMultiIter *iter, const NMPlatformLink **out_obj
has_next = nm_dedup_multi_iter_next (iter);
if (has_next) {
- nm_assert (NMP_OBJECT_GET_TYPE (iter->current->box->obj) == NMP_OBJECT_TYPE_LINK);
- NM_SET_OUT (out_obj, &(((const NMPObject *) iter->current->box->obj)->link));
+ nm_assert (NMP_OBJECT_GET_TYPE (iter->current->obj) == NMP_OBJECT_TYPE_LINK);
+ NM_SET_OUT (out_obj, &(((const NMPObject *) iter->current->obj)->link));
}
return has_next;
}
diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c
index 24e790c32c..40d876a65b 100644
--- a/src/platform/tests/test-nmp-object.c
+++ b/src/platform/tests/test-nmp-object.c
@@ -36,10 +36,18 @@ struct {
static void
test_obj_base (void)
{
- static const GObject *g = NULL;
- static const GTypeClass *k = NULL;
- static const NMPObject *o = NULL;
- static const NMPClass *c = NULL;
+ static const union {
+ GObject g;
+ NMPObject k;
+ } x = { };
+ static const union {
+ GTypeClass k;
+ NMPClass c;
+ } l = { };
+ static const GObject *g = &x.g;
+ static const GTypeClass *k = &l.k;
+ static const NMPObject *o = &x.k;
+ static const NMPClass *c = &l.c;
NMObjBaseInst *obj;
gs_unref_object GCancellable *obj_cancellable = g_cancellable_new ();
@@ -54,9 +62,8 @@ test_obj_base (void)
STATIC_ASSERT (&g->g_type_instance == (void *) &o->_class);
STATIC_ASSERT (&g->g_type_instance.g_class == (void *) &o->_class);
- STATIC_ASSERT (&g->ref_count == (void *) &o->_ref_count);
- STATIC_ASSERT (sizeof (o->parent) == sizeof (GTypeInstance));
+ STATIC_ASSERT (sizeof (o->parent.parent) == sizeof (GTypeInstance));
STATIC_ASSERT (&c->parent == (void *) c);
STATIC_ASSERT (&c->parent.parent.g_type_class == (void *) c);