📄 gtype.c
字号:
check_interface_info_I (iface, instance_type, &tmp_info); iholder->info = g_memdup (&tmp_info, sizeof (tmp_info)); } return iholder; /* we don't modify write lock upon returning NULL */}static voidtype_iface_blow_holder_info_Wm (TypeNode *iface, GType instance_type){ IFaceHolder *iholder = iface_node_get_holders_L (iface); g_assert (NODE_IS_IFACE (iface)); while (iholder->instance_type != instance_type) iholder = iholder->next; if (iholder->info && iholder->plugin) { g_free (iholder->info); iholder->info = NULL; G_WRITE_UNLOCK (&type_rw_lock); g_type_plugin_unuse (iholder->plugin); G_WRITE_LOCK (&type_rw_lock); type_data_unref_Wm (iface, FALSE); }}/* --- type structure creation/destruction --- */GTypeInstance*g_type_create_instance (GType type){ TypeNode *node; GTypeInstance *instance; GTypeClass *class; guint i; node = lookup_type_node_I (type); if (!node || !node->is_instantiatable) { g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'", type_descriptive_name_I (type)); return NULL; } /* G_TYPE_IS_ABSTRACT() is an external call: _U */ if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (type)) { g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'", type_descriptive_name_I (type)); return NULL; } class = g_type_class_ref (type); if (node->data->instance.n_preallocs) { G_WRITE_LOCK (&type_rw_lock); if (!node->data->instance.mem_chunk) node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node), node->data->instance.instance_size, (node->data->instance.instance_size * node->data->instance.n_preallocs), G_ALLOC_AND_FREE); instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk); G_WRITE_UNLOCK (&type_rw_lock); } else instance = g_malloc0 (node->data->instance.instance_size); /* fine without read lock */ for (i = node->n_supers; i > 0; i--) { TypeNode *pnode; pnode = lookup_type_node_I (node->supers[i]); if (pnode->data->instance.instance_init) { instance->g_class = pnode->data->instance.class; pnode->data->instance.instance_init (instance, class); } } instance->g_class = class; if (node->data->instance.instance_init) node->data->instance.instance_init (instance, class); return instance;}voidg_type_free_instance (GTypeInstance *instance){ TypeNode *node; GTypeClass *class; g_return_if_fail (instance != NULL && instance->g_class != NULL); class = instance->g_class; node = lookup_type_node_I (class->g_type); if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class) { g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'", type_descriptive_name_I (class->g_type)); return; } /* G_TYPE_IS_ABSTRACT() is an external call: _U */ if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (NODE_TYPE (node))) { g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'", NODE_NAME (node)); return; } instance->g_class = NULL;#ifdef G_ENABLE_DEBUG memset (instance, 0xaa, node->data->instance.instance_size); /* debugging hack */#endif if (node->data->instance.n_preallocs) { G_WRITE_LOCK (&type_rw_lock); g_chunk_free (instance, node->data->instance.mem_chunk); G_WRITE_UNLOCK (&type_rw_lock); } else g_free (instance); g_type_class_unref (class);}static gbooleantype_iface_vtable_init_Wm (TypeNode *iface, TypeNode *node){ IFaceEntry *entry = type_lookup_iface_entry_L (node, iface); IFaceHolder *iholder; GTypeInterface *vtable = NULL; TypeNode *pnode; /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */ iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), TRUE); if (!iholder) return FALSE; /* we don't modify write lock upon FALSE */ g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info); pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); if (pnode) /* want to copy over parent iface contents */ { IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface); if (pentry) vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size); } if (!vtable) vtable = g_malloc0 (iface->data->iface.vtable_size); entry->vtable = vtable; vtable->g_type = NODE_TYPE (iface); vtable->g_instance_type = NODE_TYPE (node); if (iface->data->iface.vtable_init_base || iholder->info->interface_init) { G_WRITE_UNLOCK (&type_rw_lock); if (iface->data->iface.vtable_init_base) iface->data->iface.vtable_init_base (vtable); if (iholder->info->interface_init) iholder->info->interface_init (vtable, iholder->info->interface_data); G_WRITE_LOCK (&type_rw_lock); } return TRUE; /* write lock modified */}static gbooleantype_iface_vtable_finalize_Wm (TypeNode *iface, TypeNode *node, GTypeInterface *vtable){ IFaceEntry *entry = type_lookup_iface_entry_L (node, iface); IFaceHolder *iholder; /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */ iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), FALSE); if (!iholder) return FALSE; /* we don't modify write lock upon FALSE */ g_assert (entry && entry->vtable == vtable && iholder->info); entry->vtable = NULL; if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base) { G_WRITE_UNLOCK (&type_rw_lock); if (iholder->info->interface_finalize) iholder->info->interface_finalize (vtable, iholder->info->interface_data); if (iface->data->iface.vtable_finalize_base) iface->data->iface.vtable_finalize_base (vtable); G_WRITE_LOCK (&type_rw_lock); } vtable->g_type = 0; vtable->g_instance_type = 0; g_free (vtable); type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node)); return TRUE; /* write lock modified */}static voidtype_class_init_Wm (TypeNode *node, GTypeClass *pclass){ GSList *slist, *init_slist = NULL; GTypeClass *class; IFaceEntry *entry; TypeNode *bnode, *pnode; guint i; g_assert (node->is_classed && node->data && node->data->class.class_size && !node->data->class.class); class = g_malloc0 (node->data->class.class_size); node->data->class.class = class; if (pclass) { TypeNode *pnode = lookup_type_node_I (pclass->g_type); memcpy (class, pclass, pnode->data->class.class_size); } class->g_type = NODE_TYPE (node); G_WRITE_UNLOCK (&type_rw_lock); /* stack all base class initialization functions, so we * call them in ascending order. */ for (bnode = node; bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode))) if (bnode->data->class.class_init_base) init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base); for (slist = init_slist; slist; slist = slist->next) { GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data; class_init_base (class); } g_slist_free (init_slist); if (node->data->class.class_init) node->data->class.class_init (class, (gpointer) node->data->class.class_data); G_WRITE_LOCK (&type_rw_lock); /* ok, we got the class done, now initialize all interfaces, either * from parent, or through our holder info */ pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); entry = CLASSED_NODE_IFACES_ENTRIES (node) + 0; while (entry) { g_assert (entry->vtable == NULL); if (!type_iface_vtable_init_Wm (lookup_type_node_I (entry->iface_type), node)) { guint j; /* type_iface_vtable_init_Wm() doesn't modify write lock upon FALSE, * need to get this interface from parent */ g_assert (pnode != NULL); for (j = 0; j < CLASSED_NODE_N_IFACES (pnode); j++) { IFaceEntry *pentry = CLASSED_NODE_IFACES_ENTRIES (pnode) + j; if (pentry->iface_type == entry->iface_type) { entry->vtable = pentry->vtable; break; } } g_assert (entry->vtable != NULL); } /* refetch entry, IFACES_ENTRIES might be modified */ for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++) if (!CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable) entry = CLASSED_NODE_IFACES_ENTRIES (node) + i; }}static voidtype_data_finalize_class_ifaces_Wm (TypeNode *node){ IFaceEntry *entry; guint i; g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0); g_message ("finalizing interfaces for %sClass `%s'", type_descriptive_name_I (NODE_FUNDAMENTAL_TYPE (node)), type_descriptive_name_I (NODE_TYPE (node))); for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++) if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable && CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node)) entry = CLASSED_NODE_IFACES_ENTRIES (node) + i; while (entry) { if (!type_iface_vtable_finalize_Wm (lookup_type_node_I (entry->iface_type), node, entry->vtable)) { /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE, * iface vtable came from parent */ entry->vtable = NULL; } /* refetch entry, IFACES_ENTRIES might be modified */ for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++) if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable && CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node)) entry = CLASSED_NODE_IFACES_ENTRIES (node) + i; }}static voidtype_data_finalize_class_U (TypeNode *node, ClassData *cdata){ GTypeClass *class = cdata->class; TypeNode *bnode; g_assert (cdata->class && cdata->common.ref_count == 0); if (cdata->class_finalize) cdata->class_finalize (class, (gpointer) cdata->class_data); /* call all base class destruction functions in descending order */ if (cdata->class_finalize_base) cdata->class_finalize_base (class); for (bnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode))) if (bnode->data->class.class_finalize_base) bnode->data->class.class_finalize_base (class); class->g_type = 0; g_free (cdata->class);}static voidtype_data_last_unref_Wm (GType type, gboolean uncached){ TypeNode *node = lookup_type_node_I (type); g_return_if_fail (node != NULL && node->plugin != NULL); if (!node->data || node->data->common.ref_count == 0) { g_warning ("cannot drop last reference to unreferenced type `%s'", type_descriptive_name_I (type)); return; } if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs) { guint i; G_WRITE_UNLOCK (&type_rw_lock); G_READ_LOCK (&type_rw_lock); for (i = 0; i < static_n_class_cache_funcs; i++) { GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func; gpointer cache_data = static_class_cache_funcs[i].cache_data; gboolean need_break; G_READ_UNLOCK (&type_rw_lock); need_break = cache_func (cache_data, node->data->class.class); G_READ_LOCK (&type_rw_lock); if (!node->data || node->data->common.ref_count == 0) INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node)); if (need_break) break; } G_READ_UNLOCK (&type_rw_lock); G_WRITE_LOCK (&type_rw_lock); } if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */ node->data->common.ref_count -= 1; else { GType ptype = NODE_PARENT_TYPE (node); TypeData *tdata; node->data->common.ref_count = 0; if (node->is_instantiatable && node->data->instance.mem_chunk) { g_mem_chunk_destroy (node->data->instance.mem_chunk); node->data->instance.mem_chunk = NULL; } tdata = node->data; if (node->is_classed && tdata->class.class) { if (CLASSED_NODE_N_IFACES (node)) type_data_finalize_class_ifaces_Wm (node); node->mutatable_check_cache = FALSE; node->data = NULL; G_WRITE_UNLOCK (&type_rw_lock); type_data_finalize_class_U (node, &tdata->class); G_WRITE_LOCK (&type_rw_lock); } else { node->mutatable_check_cache = FALSE; node->data = NULL; } /* freeing tdata->common.value_table and its contents is taking care of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -