📄 gtype.c
字号:
} return TRUE;}static gbooleancheck_interface_info_I (TypeNode *iface, GType instance_type, const GInterfaceInfo *info){ if ((info->interface_finalize || info->interface_data) && !info->interface_init) { g_warning ("interface type `%s' for type `%s' comes without initializer", NODE_NAME (iface), type_descriptive_name_I (instance_type)); return FALSE; } return TRUE;}/* --- type info (type node data) --- */static voidtype_data_make_W (TypeNode *node, const GTypeInfo *info, const GTypeValueTable *value_table){ TypeData *data; GTypeValueTable *vtable = NULL; guint vtable_size = 0; g_assert (node->data == NULL && info != NULL); if (!value_table) { TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); if (pnode) vtable = pnode->data->common.value_table; else { static const GTypeValueTable zero_vtable = { NULL, }; value_table = &zero_vtable; } } if (value_table) { /* need to setup vtable_size since we have to allocate it with data in one chunk */ vtable_size = sizeof (GTypeValueTable); if (value_table->collect_format) vtable_size += strlen (value_table->collect_format); if (value_table->lcopy_format) vtable_size += strlen (value_table->lcopy_format); vtable_size += 2; } if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */ { data = g_malloc0 (sizeof (InstanceData) + vtable_size); if (vtable_size) vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData)); data->instance.class_size = info->class_size; data->instance.class_init_base = info->base_init; data->instance.class_finalize_base = info->base_finalize; data->instance.class_init = info->class_init; data->instance.class_finalize = info->class_finalize; data->instance.class_data = info->class_data; data->instance.class = NULL; data->instance.instance_size = info->instance_size;#ifdef DISABLE_MEM_POOLS data->instance.n_preallocs = 0;#else /* !DISABLE_MEM_POOLS */ data->instance.n_preallocs = MIN (info->n_preallocs, 1024);#endif /* !DISABLE_MEM_POOLS */ data->instance.instance_init = info->instance_init; data->instance.mem_chunk = NULL; } else if (node->is_classed) /* only classed */ { data = g_malloc0 (sizeof (ClassData) + vtable_size); if (vtable_size) vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData)); data->class.class_size = info->class_size; data->class.class_init_base = info->base_init; data->class.class_finalize_base = info->base_finalize; data->class.class_init = info->class_init; data->class.class_finalize = info->class_finalize; data->class.class_data = info->class_data; data->class.class = NULL; } else if (NODE_IS_IFACE (node)) { data = g_malloc0 (sizeof (IFaceData) + vtable_size); if (vtable_size) vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData)); data->iface.vtable_size = info->class_size; data->iface.vtable_init_base = info->base_init; data->iface.vtable_finalize_base = info->base_finalize; } else { data = g_malloc0 (sizeof (CommonData) + vtable_size); if (vtable_size) vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData)); } node->data = data; node->data->common.ref_count = 1; if (vtable_size) { gchar *p; /* we allocate the vtable and its strings together with the type data, so * children can take over their parent's vtable pointer, and we don't * need to worry freeing it or not when the child data is destroyed */ *vtable = *value_table; p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable)); p[0] = 0; vtable->collect_format = p; if (value_table->collect_format) { strcat (p, value_table->collect_format); p += strlen (value_table->collect_format); } p++; p[0] = 0; vtable->lcopy_format = p; if (value_table->lcopy_format) strcat (p, value_table->lcopy_format); } node->data->common.value_table = vtable; node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL && !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags)))); g_assert (node->data->common.value_table != NULL); /* paranoid */}static inline voidtype_data_ref_Wm (TypeNode *node){ if (!node->data) { TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); GTypeInfo tmp_info; GTypeValueTable tmp_value_table; g_assert (node->plugin != NULL); if (pnode) { type_data_ref_Wm (pnode); if (node->data) INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node)); } memset (&tmp_info, 0, sizeof (tmp_info)); memset (&tmp_value_table, 0, sizeof (tmp_value_table)); G_WRITE_UNLOCK (&type_rw_lock); g_type_plugin_use (node->plugin); g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table); G_WRITE_LOCK (&type_rw_lock); if (node->data) INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node)); check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (node), NODE_NAME (node), &tmp_info); type_data_make_W (node, &tmp_info, check_value_table_I (NODE_NAME (node), &tmp_value_table) ? &tmp_value_table : NULL); } else { g_assert (node->data->common.ref_count > 0); node->data->common.ref_count += 1; }}static inline voidtype_data_unref_Wm (TypeNode *node, gboolean uncached){ g_assert (node->data && node->data->common.ref_count); if (node->data->common.ref_count > 1) node->data->common.ref_count -= 1; else { if (!node->plugin) { g_warning ("static type `%s' unreferenced too often", NODE_NAME (node)); return; } type_data_last_unref_Wm (NODE_TYPE (node), uncached); }}static voidtype_node_add_iface_entry_W (TypeNode *node, GType iface_type){ IFaceEntry *entries; guint i; g_assert (node->is_instantiatable && CLASSED_NODE_N_IFACES (node) < MAX_N_IFACES); entries = CLASSED_NODE_IFACES_ENTRIES (node); for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++) if (entries[i].iface_type == iface_type) { /* this can (should) only happen if our parent type already conformed * to iface_type and node got it's own holder info. here, our * children should already have entries with NULL vtables, so * we're actually done. */ g_assert (entries[i].vtable == NULL); return; } else if (entries[i].iface_type > iface_type) break; CLASSED_NODE_N_IFACES (node) += 1; CLASSED_NODE_IFACES_ENTRIES (node) = g_renew (IFaceEntry, CLASSED_NODE_IFACES_ENTRIES (node), CLASSED_NODE_N_IFACES (node)); entries = CLASSED_NODE_IFACES_ENTRIES (node); g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (CLASSED_NODE_N_IFACES (node) - i - 1)); entries[i].iface_type = iface_type; entries[i].vtable = NULL; for (i = 0; i < node->n_children; i++) type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), iface_type);}static voidtype_add_interface_W (TypeNode *node, TypeNode *iface, const GInterfaceInfo *info, GTypePlugin *plugin){ IFaceHolder *iholder = g_new0 (IFaceHolder, 1); /* we must not call any functions of GInterfaceInfo from within here, since * we got most probably called from _within_ a type registration function */ g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin))); iholder->next = iface_node_get_holders_L (iface); iface_node_set_holders_W (iface, iholder); iholder->instance_type = NODE_TYPE (node); iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL; iholder->plugin = plugin; type_node_add_iface_entry_W (node, NODE_TYPE (iface));}static voidtype_iface_add_prerequisite_W (TypeNode *iface, TypeNode *prerequisite_node){ GType prerequisite_type = NODE_TYPE (prerequisite_node); GType *prerequisites, *dependants; guint n_dependants, i; g_assert (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface) < MAX_N_PREREQUISITES && (prerequisite_node->is_instantiatable || NODE_IS_IFACE (prerequisite_node))); prerequisites = IFACE_NODE_PREREQUISITES (iface); for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++) if (prerequisites[i] == prerequisite_type) return; /* we already have that prerequisiste */ else if (prerequisites[i] > prerequisite_type) break; IFACE_NODE_N_PREREQUISITES (iface) += 1; IFACE_NODE_PREREQUISITES (iface) = g_renew (GType, IFACE_NODE_PREREQUISITES (iface), IFACE_NODE_N_PREREQUISITES (iface)); prerequisites = IFACE_NODE_PREREQUISITES (iface); g_memmove (prerequisites + i + 1, prerequisites + i, sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1)); prerequisites[i] = prerequisite_type; /* we want to get notified when prerequisites get added to prerequisite_node */ if (NODE_IS_IFACE (prerequisite_node)) { dependants = iface_node_get_dependants_array_L (prerequisite_node); n_dependants = dependants ? dependants[0] : 0; n_dependants += 1; dependants = g_renew (GType, dependants, n_dependants + 1); dependants[n_dependants] = NODE_TYPE (iface); dependants[0] = n_dependants; iface_node_set_dependants_array_W (prerequisite_node, dependants); } /* we need to notify all dependants */ dependants = iface_node_get_dependants_array_L (iface); n_dependants = dependants ? dependants[0] : 0; for (i = 1; i <= n_dependants; i++) type_iface_add_prerequisite_W (lookup_type_node_I (dependants[i]), prerequisite_node);}voidg_type_interface_add_prerequisite (GType interface_type, GType prerequisite_type){ TypeNode *iface, *prerequisite_node; IFaceHolder *holders; g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type)); /* G_TYPE_IS_INTERFACE() is an external call: _U */ g_return_if_fail (!g_type_is_a (interface_type, prerequisite_type)); g_return_if_fail (!g_type_is_a (prerequisite_type, interface_type)); iface = lookup_type_node_I (interface_type); prerequisite_node = lookup_type_node_I (prerequisite_type); if (!iface || !prerequisite_node || !NODE_IS_IFACE (iface)) { g_warning ("interface type `%s' or prerequisite type `%s' invalid", type_descriptive_name_I (interface_type), type_descriptive_name_I (prerequisite_type)); return; } G_WRITE_LOCK (&type_rw_lock); holders = iface_node_get_holders_L (iface); if (holders) { G_WRITE_UNLOCK (&type_rw_lock); g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'", type_descriptive_name_I (prerequisite_type), type_descriptive_name_I (interface_type), type_descriptive_name_I (holders->instance_type)); return; } if (prerequisite_node->is_instantiatable) { guint i; /* can have at most one publically installable instantiatable prerequisite */ for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++) { TypeNode *prnode = lookup_type_node_I (IFACE_NODE_PREREQUISITES (iface)[i]); if (prnode->is_instantiatable) { G_WRITE_UNLOCK (&type_rw_lock); g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'", type_descriptive_name_I (prerequisite_type), type_descriptive_name_I (interface_type), type_descriptive_name_I (NODE_TYPE (prnode))); return; } } for (i = 0; i < prerequisite_node->n_supers + 1; i++) type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisite_node->supers[i])); G_WRITE_UNLOCK (&type_rw_lock); } else if (NODE_IS_IFACE (prerequisite_node)) { GType *prerequisites; guint i; prerequisites = IFACE_NODE_PREREQUISITES (prerequisite_node); for (i = 0; i < IFACE_NODE_N_PREREQUISITES (prerequisite_node); i++) type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisites[i])); type_iface_add_prerequisite_W (iface, prerequisite_node); G_WRITE_UNLOCK (&type_rw_lock); } else { G_WRITE_UNLOCK (&type_rw_lock); g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface", type_descriptive_name_I (prerequisite_type), type_descriptive_name_I (interface_type)); }}static IFaceHolder*type_iface_peek_holder_L (TypeNode *iface, GType instance_type){ IFaceHolder *iholder; g_assert (NODE_IS_IFACE (iface)); iholder = iface_node_get_holders_L (iface); while (iholder && iholder->instance_type != instance_type) iholder = iholder->next; return iholder;}static IFaceHolder*type_iface_retrieve_holder_info_Wm (TypeNode *iface, GType instance_type, gboolean need_info){ IFaceHolder *iholder = type_iface_peek_holder_L (iface, instance_type); if (iholder && !iholder->info && need_info) { GInterfaceInfo tmp_info; g_assert (iholder->plugin != NULL); type_data_ref_Wm (iface); if (iholder->info) INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface)); memset (&tmp_info, 0, sizeof (tmp_info)); G_WRITE_UNLOCK (&type_rw_lock); g_type_plugin_use (iholder->plugin); g_type_plugin_complete_interface_info (iholder->plugin, instance_type, NODE_TYPE (iface), &tmp_info); G_WRITE_LOCK (&type_rw_lock); if (iholder->info) INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -